blob: 8a5de0150ad2efc3825096edb3f2cfc9f5c1a69a [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eugene Zelenkodde94e42017-01-30 23:21:32 +000010#include "MCTargetDesc/MipsABIFlagsSection.h"
Eric Christophera5762812015-01-26 17:33:46 +000011#include "MCTargetDesc/MipsABIInfo.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000012#include "MCTargetDesc/MipsBaseInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000013#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000014#include "MCTargetDesc/MipsMCTargetDesc.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Zoran Jovanovic375b60d2017-05-30 09:33:43 +000016#include "llvm/ADT/APFloat.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000017#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000018#include "llvm/ADT/SmallVector.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000019#include "llvm/ADT/StringRef.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "llvm/ADT/StringSwitch.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000021#include "llvm/ADT/Triple.h"
22#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000023#include "llvm/BinaryFormat/ELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCExpr.h"
26#include "llvm/MC/MCInst.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000027#include "llvm/MC/MCInstrDesc.h"
28#include "llvm/MC/MCObjectFileInfo.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000029#include "llvm/MC/MCParser/MCAsmLexer.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000030#include "llvm/MC/MCParser/MCAsmParser.h"
31#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000032#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000033#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000034#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000035#include "llvm/MC/MCStreamer.h"
36#include "llvm/MC/MCSubtargetInfo.h"
37#include "llvm/MC/MCSymbol.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000038#include "llvm/MC/MCSymbolELF.h"
39#include "llvm/MC/MCValue.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000043#include "llvm/Support/Debug.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000044#include "llvm/Support/ErrorHandling.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000045#include "llvm/Support/MathExtras.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000046#include "llvm/Support/SMLoc.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000047#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000048#include "llvm/Support/TargetRegistry.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000049#include "llvm/Support/raw_ostream.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000050#include <algorithm>
51#include <cassert>
52#include <cstdint>
Toma Tabacu9db22db2014-09-09 10:15:38 +000053#include <memory>
Eugene Zelenkodde94e42017-01-30 23:21:32 +000054#include <string>
55#include <utility>
Rafael Espindola870c4e92012-01-11 03:56:41 +000056
57using namespace llvm;
58
Chandler Carruthe96dd892014-04-21 22:55:11 +000059#define DEBUG_TYPE "mips-asm-parser"
60
Joey Gouly0e76fa72013-09-12 10:28:05 +000061namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000062
Joey Gouly0e76fa72013-09-12 10:28:05 +000063class MCInstrInfo;
Eugene Zelenkodde94e42017-01-30 23:21:32 +000064
65} // end namespace llvm
Joey Gouly0e76fa72013-09-12 10:28:05 +000066
Rafael Espindola870c4e92012-01-11 03:56:41 +000067namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000068
Jack Carter0b744b32012-10-04 02:29:46 +000069class MipsAssemblerOptions {
70public:
Eugene Zelenkodde94e42017-01-30 23:21:32 +000071 MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000072
Toma Tabacu9db22db2014-09-09 10:15:38 +000073 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000074 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000075 Reorder = Opts->isReorder();
76 Macro = Opts->isMacro();
77 Features = Opts->getFeatures();
78 }
79
Toma Tabacub19cf202015-04-27 13:12:59 +000080 unsigned getATRegIndex() const { return ATReg; }
81 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000082 if (Reg > 31)
83 return false;
84
85 ATReg = Reg;
86 return true;
87 }
Jack Carter0b744b32012-10-04 02:29:46 +000088
Toma Tabacu9db22db2014-09-09 10:15:38 +000089 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000090 void setReorder() { Reorder = true; }
91 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000092
Toma Tabacu9db22db2014-09-09 10:15:38 +000093 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000094 void setMacro() { Macro = true; }
95 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000096
Toma Tabacu465acfd2015-06-09 13:33:26 +000097 const FeatureBitset &getFeatures() const { return Features; }
98 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000099
Daniel Sandersf0df2212014-08-04 12:20:00 +0000100 // Set of features that are either architecture features or referenced
101 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
102 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
103 // The reason we need this mask is explained in the selectArch function.
104 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000105 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +0000106
Jack Carter0b744b32012-10-04 02:29:46 +0000107private:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000108 unsigned ATReg = 1;
109 bool Reorder = true;
110 bool Macro = true;
Toma Tabacu465acfd2015-06-09 13:33:26 +0000111 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +0000112};
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000113
114} // end anonymous namespace
Jack Carter0b744b32012-10-04 02:29:46 +0000115
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000116const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
117 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
118 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
119 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
120 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
121 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
122 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
123 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
124 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
125};
126
Jack Carter0b744b32012-10-04 02:29:46 +0000127namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000128
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000130 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000131 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000132 return static_cast<MipsTargetStreamer &>(TS);
133 }
134
Eric Christophera5762812015-01-26 17:33:46 +0000135 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000136 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000137 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
138 // nullptr, which indicates that no function is currently
139 // selected. This usually happens after an '.end func'
140 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000141 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000142 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000143 bool IsCpRestoreSet;
144 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000145 unsigned CpSaveLocation;
146 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
147 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000148
Daniel Sandersef638fe2014-10-03 15:37:37 +0000149 // Print a warning along with its fix-it message at the given range.
150 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
151 SMRange Range, bool ShowColors = true);
152
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000153#define GET_ASSEMBLER_HEADER
154#include "MipsGenAsmMatcher.inc"
155
Daniel Sandersc5537422016-07-27 13:49:44 +0000156 unsigned
157 checkEarlyTargetMatchPredicate(MCInst &Inst,
158 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000159 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
160
Chad Rosier49963552012-10-13 00:26:04 +0000161 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000162 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000163 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000164 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000165
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000166 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000167 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000168
Toma Tabacu13964452014-09-04 13:23:44 +0000169 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000170
Toma Tabacu13964452014-09-04 13:23:44 +0000171 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000172
Craig Topper55bc6cb2017-02-08 02:54:12 +0000173 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
174
David Blaikie960ea3f2014-06-08 16:18:35 +0000175 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
176 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000177
Craig Topper56c590a2014-04-29 07:58:02 +0000178 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000179
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000180 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
181 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000182 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000183 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000184 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
185 SMLoc S);
186 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
187 OperandMatchResultTy parseImm(OperandVector &Operands);
188 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
189 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000190 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
191 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
192 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000193
David Blaikie960ea3f2014-06-08 16:18:35 +0000194 bool searchSymbolAlias(OperandVector &Operands);
195
Toma Tabacu13964452014-09-04 13:23:44 +0000196 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000197
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000198 enum MacroExpanderResultTy {
199 MER_NotAMacro,
200 MER_Success,
201 MER_Fail,
202 };
Jack Carter30a59822012-10-04 04:03:53 +0000203
Matheus Almeida3813d572014-06-19 14:39:14 +0000204 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000205 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
206 MCStreamer &Out,
207 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000208
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000209 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
210 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000211
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000212 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000213 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000214 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000215
Toma Tabacuf712ede2015-06-17 14:31:51 +0000216 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
217 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000219
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000220 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
221
Toma Tabacu00e98672015-05-01 12:19:27 +0000222 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000223 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000224
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000225 bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU,
226 SMLoc IDLoc, MCStreamer &Out,
227 const MCSubtargetInfo *STI);
228
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000229 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
230 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000231 SMLoc IDLoc, MCStreamer &Out,
232 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000233
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000234 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000236
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000237 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000238 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
239
240 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
241 const MCSubtargetInfo *STI, bool IsImmOpnd);
242
243 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000245
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000246 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000248
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000249 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
250 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000251
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000252 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
253 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000254
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000255 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
256 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000257
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000258 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
259 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000260 const bool Signed);
261
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000262 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000263 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000264
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000265 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
266 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000267
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000268 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
269 const MCSubtargetInfo *STI);
270
271 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000272 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000273
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000274 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000275 MCStreamer &Out, const MCSubtargetInfo *STI);
276 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
277 const MCSubtargetInfo *STI);
278 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
279 const MCSubtargetInfo *STI);
280 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
281 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000282
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000283 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
284 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000285
Simon Dardis3c82a642017-02-08 16:25:05 +0000286 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
287 const MCSubtargetInfo *STI);
288
289 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
290 const MCSubtargetInfo *STI);
291
292 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
293 const MCSubtargetInfo *STI);
294
295 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
296 const MCSubtargetInfo *STI);
297
Simon Dardisaff4d142016-10-18 14:28:00 +0000298 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
299 const MCSubtargetInfo *STI, bool IsLoad);
300
Simon Dardis43115a12016-11-21 20:30:41 +0000301 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
302 const MCSubtargetInfo *STI);
303
304 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
305 const MCSubtargetInfo *STI);
306
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000307 bool reportParseError(Twine ErrorMsg);
308 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000309
Jack Carterb5cf5902013-04-17 00:18:04 +0000310 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000311
312 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000313 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000314 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000315 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000316 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000317 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000318 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000319 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000320 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000321 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000322 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000323 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000324 bool parseInsnDirective();
Simon Dardis1c73fcc2017-06-22 10:41:51 +0000325 bool parseRSectionDirective(StringRef Section);
Simon Atanasyanbe186202016-02-11 06:45:54 +0000326 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000327
328 bool parseSetAtDirective();
329 bool parseSetNoAtDirective();
330 bool parseSetMacroDirective();
331 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000332 bool parseSetMsaDirective();
333 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000334 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000335 bool parseSetReorderDirective();
336 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000337 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000338 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000339 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000340 bool parseSetOddSPRegDirective();
341 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000342 bool parseSetPopDirective();
343 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000344 bool parseSetSoftFloatDirective();
345 bool parseSetHardFloatDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +0000346 bool parseSetMtDirective();
347 bool parseSetNoMtDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000348
Jack Carterd76b2372013-03-21 21:44:16 +0000349 bool parseSetAssignment();
350
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000351 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000352 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000353 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000354 bool parseDirectiveDtpRelWord();
355 bool parseDirectiveDtpRelDWord();
356 bool parseDirectiveTpRelWord();
357 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000358 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000359 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000360 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
361 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000362
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000363 bool parseInternalDirectiveReallowModule();
364
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000365 bool eatComma(StringRef ErrorStr);
366
Jack Carter1ac53222013-02-20 23:11:17 +0000367 int matchCPURegisterName(StringRef Symbol);
368
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000369 int matchHWRegsRegisterName(StringRef Symbol);
370
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000371 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000372
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000373 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000374
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000375 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000376
Jack Carter5dc8ac92013-09-25 23:50:44 +0000377 int matchMSA128RegisterName(StringRef Name);
378
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000379 int matchMSA128CtrlRegisterName(StringRef Name);
380
Jack Carterd0bd6422013-04-18 00:41:53 +0000381 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000382
Toma Tabacu89a712b2015-04-15 10:48:56 +0000383 /// Returns the internal register number for the current AT. Also checks if
384 /// the current AT is unavailable (set to $0) and gives an error if it is.
385 /// This should be used in pseudo-instruction expansions which need AT.
386 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000387
Simon Dardis3aa8a902017-02-06 12:43:46 +0000388 bool canUseATReg();
389
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000390 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
391 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000392
393 // Helper function that checks if the value of a vector index is within the
394 // boundaries of accepted values for each RegisterKind
395 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
396 bool validateMSAIndex(int Val, int RegKind);
397
Daniel Sandersf0df2212014-08-04 12:20:00 +0000398 // Selects a new architecture by updating the FeatureBits with the necessary
399 // info including implied dependencies.
400 // Internally, it clears all the feature bits related to *any* architecture
401 // and selects the new one using the ToggleFeature functionality of the
402 // MCSubtargetInfo object that handles implied dependencies. The reason we
403 // clear all the arch related bits manually is because ToggleFeature only
404 // clears the features that imply the feature being cleared and not the
405 // features implied by the feature being cleared. This is easier to see
406 // with an example:
407 // --------------------------------------------------
408 // | Feature | Implies |
409 // | -------------------------------------------------|
410 // | FeatureMips1 | None |
411 // | FeatureMips2 | FeatureMips1 |
412 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
413 // | FeatureMips4 | FeatureMips3 |
414 // | ... | |
415 // --------------------------------------------------
416 //
417 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
418 // FeatureMipsGP64 | FeatureMips1)
419 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
420 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000421 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000422 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000423 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
424 STI.setFeatureBits(FeatureBits);
425 setAvailableFeatures(
426 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000427 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000428 }
429
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000430 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000431 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000432 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000433 setAvailableFeatures(
434 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000435 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000436 }
437 }
438
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000439 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000440 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000441 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000442 setAvailableFeatures(
443 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000444 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000445 }
446 }
447
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000448 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
449 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000450 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000451 }
452
453 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
454 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000455 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000456 }
457
Rafael Espindola870c4e92012-01-11 03:56:41 +0000458public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000459 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000460 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000461 Match_RequiresDifferentOperands,
462 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000463 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000464 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000465 Match_NonZeroOperandForSync,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000466#define GET_OPERAND_DIAGNOSTIC_TYPES
467#include "MipsGenAsmMatcher.inc"
468#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000469 };
470
Akira Hatanakab11ef082015-11-14 06:35:56 +0000471 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000472 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000473 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000474 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
475 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000476 MCAsmParserExtension::Initialize(parser);
477
Toma Tabacu11e14a92015-04-21 11:50:52 +0000478 parser.addAliasForDirective(".asciiz", ".asciz");
479
Jack Carterb4dbc172012-09-05 23:34:03 +0000480 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000481 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000482
Toma Tabacu9db22db2014-09-09 10:15:38 +0000483 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000484 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000485 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000486
Toma Tabacu9db22db2014-09-09 10:15:38 +0000487 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000488 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000489 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000490
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000491 getTargetStreamer().updateABIInfo(*this);
492
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000493 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000494 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000495
496 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000497
Rafael Espindola699281c2016-05-18 11:58:50 +0000498 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000499
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000500 IsCpRestoreSet = false;
501 CpRestoreOffset = -1;
502
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000503 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000504 if ((TheTriple.getArch() == Triple::mips) ||
505 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000506 IsLittleEndian = false;
507 else
508 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000509 }
510
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000511 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
512 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
513
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000514 bool isGP64bit() const {
515 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
516 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000517
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000518 bool isFP64bit() const {
519 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
520 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000521
Eric Christophera5762812015-01-26 17:33:46 +0000522 const MipsABIInfo &getABI() const { return ABI; }
523 bool isABI_N32() const { return ABI.IsN32(); }
524 bool isABI_N64() const { return ABI.IsN64(); }
525 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000526 bool isABI_FPXX() const {
527 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
528 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000529
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000530 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000531 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000532 }
533
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000534 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000535 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000536 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000537
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000538 bool hasMips1() const {
539 return getSTI().getFeatureBits()[Mips::FeatureMips1];
540 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000541
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000542 bool hasMips2() const {
543 return getSTI().getFeatureBits()[Mips::FeatureMips2];
544 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000545
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000546 bool hasMips3() const {
547 return getSTI().getFeatureBits()[Mips::FeatureMips3];
548 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000549
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000550 bool hasMips4() const {
551 return getSTI().getFeatureBits()[Mips::FeatureMips4];
552 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000553
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000554 bool hasMips5() const {
555 return getSTI().getFeatureBits()[Mips::FeatureMips5];
556 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000557
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000558 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000559 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000560 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000561
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000562 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000563 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000564 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000565
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000566 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000567 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000568 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000569
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000570 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000571 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000572 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000573
Daniel Sanders17793142015-02-18 16:24:50 +0000574 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000575 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000576 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000577
Daniel Sanders17793142015-02-18 16:24:50 +0000578 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000579 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000580 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000581
Daniel Sanders17793142015-02-18 16:24:50 +0000582 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000583 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000584 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000585
Daniel Sanders17793142015-02-18 16:24:50 +0000586 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000587 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000588 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000589
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000590 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000591 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000592 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000593
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000594 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000595 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000596 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000597
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000598 bool hasDSP() const {
599 return getSTI().getFeatureBits()[Mips::FeatureDSP];
600 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000601
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000602 bool hasDSPR2() const {
603 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
604 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000605
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000606 bool hasDSPR3() const {
607 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
608 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000609
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000610 bool hasMSA() const {
611 return getSTI().getFeatureBits()[Mips::FeatureMSA];
612 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000613
Kai Nackee0245392015-01-27 19:11:28 +0000614 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000615 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000616 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000617
Daniel Sandersa6994442015-08-18 12:33:54 +0000618 bool inPicMode() {
619 return IsPicEnabled;
620 }
621
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000622 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000623 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000624 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000625
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000626 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000627 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000628 }
629
Eric Christophere8ae3e32015-05-07 23:10:21 +0000630 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000631 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000632 }
Simon Dardisae719c52017-07-11 18:03:20 +0000633 bool hasMT() const {
634 return getSTI().getFeatureBits()[Mips::FeatureMT];
635 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000636
Toma Tabacud9d344b2015-04-27 14:05:04 +0000637 /// Warn if RegIndex is the same as the current AT.
638 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000639
640 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000641
642 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000643
644 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
645 AsmToken::TokenKind OperatorToken,
646 MCContext &Ctx) override {
647 switch(OperatorToken) {
648 default:
649 llvm_unreachable("Unknown token");
650 return nullptr;
651 case AsmToken::PercentCall16:
652 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
653 case AsmToken::PercentCall_Hi:
654 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
655 case AsmToken::PercentCall_Lo:
656 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
657 case AsmToken::PercentDtprel_Hi:
658 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
659 case AsmToken::PercentDtprel_Lo:
660 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
661 case AsmToken::PercentGot:
662 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
663 case AsmToken::PercentGot_Disp:
664 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
665 case AsmToken::PercentGot_Hi:
666 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
667 case AsmToken::PercentGot_Lo:
668 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
669 case AsmToken::PercentGot_Ofst:
670 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
671 case AsmToken::PercentGot_Page:
672 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
673 case AsmToken::PercentGottprel:
674 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
675 case AsmToken::PercentGp_Rel:
676 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
677 case AsmToken::PercentHi:
678 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
679 case AsmToken::PercentHigher:
680 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
681 case AsmToken::PercentHighest:
682 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
683 case AsmToken::PercentLo:
684 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
685 case AsmToken::PercentNeg:
686 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
687 case AsmToken::PercentPcrel_Hi:
688 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
689 case AsmToken::PercentPcrel_Lo:
690 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
691 case AsmToken::PercentTlsgd:
692 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
693 case AsmToken::PercentTlsldm:
694 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
695 case AsmToken::PercentTprel_Hi:
696 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
697 case AsmToken::PercentTprel_Lo:
698 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
699 }
700 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000701};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000702
703/// MipsOperand - Instances of this class represent a parsed Mips machine
704/// instruction.
705class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000706public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000707 /// Broad categories of register classes
708 /// The exact class is finalized by the render method.
709 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000710 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000711 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000712 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000713 RegKind_FCC = 4, /// FCC
714 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
715 RegKind_MSACtrl = 16, /// MSA control registers
716 RegKind_COP2 = 32, /// COP2
717 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
718 /// context).
719 RegKind_CCR = 128, /// CCR
720 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000721 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000722 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000723 /// Potentially any (e.g. $1)
724 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
725 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000726 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000727 };
728
729private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000730 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000731 k_Immediate, /// An immediate (possibly involving symbol references)
732 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000733 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000734 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000735 k_RegList, /// A physical register list
736 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000737 } Kind;
738
David Blaikie960ea3f2014-06-08 16:18:35 +0000739public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000740 MipsOperand(KindTy K, MipsAsmParser &Parser)
741 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
742
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000743 ~MipsOperand() override {
744 switch (Kind) {
745 case k_Immediate:
746 break;
747 case k_Memory:
748 delete Mem.Base;
749 break;
750 case k_RegList:
751 delete RegList.List;
752 case k_RegisterIndex:
753 case k_Token:
754 case k_RegPair:
755 break;
756 }
757 }
758
David Blaikie960ea3f2014-06-08 16:18:35 +0000759private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000760 /// For diagnostics, and checking the assembler temporary
761 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000762
Eric Christopher8996c5d2013-03-15 00:42:55 +0000763 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000764 const char *Data;
765 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000766 };
767
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000768 struct RegIdxOp {
769 unsigned Index; /// Index into the register class
770 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000771 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000772 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000773 };
774
775 struct ImmOp {
776 const MCExpr *Val;
777 };
778
779 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000780 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000781 const MCExpr *Off;
782 };
783
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000784 struct RegListOp {
785 SmallVector<unsigned, 10> *List;
786 };
787
Jack Carterb4dbc172012-09-05 23:34:03 +0000788 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000789 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000790 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000791 struct ImmOp Imm;
792 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000793 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000794 };
795
796 SMLoc StartLoc, EndLoc;
797
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000798 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000799 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
800 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000801 const MCRegisterInfo *RegInfo,
802 SMLoc S, SMLoc E,
803 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000804 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 Op->RegIdx.Index = Index;
806 Op->RegIdx.RegInfo = RegInfo;
807 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000808 Op->RegIdx.Tok.Data = Str.data();
809 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000810 Op->StartLoc = S;
811 Op->EndLoc = E;
812 return Op;
813 }
814
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000815public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000816 /// Coerce the register to GPR32 and return the real register for the current
817 /// target.
818 unsigned getGPR32Reg() const {
819 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000820 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000821 unsigned ClassID = Mips::GPR32RegClassID;
822 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000823 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000824
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000825 /// Coerce the register to GPR32 and return the real register for the current
826 /// target.
827 unsigned getGPRMM16Reg() const {
828 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
829 unsigned ClassID = Mips::GPR32RegClassID;
830 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
831 }
832
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000833 /// Coerce the register to GPR64 and return the real register for the current
834 /// target.
835 unsigned getGPR64Reg() const {
836 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
837 unsigned ClassID = Mips::GPR64RegClassID;
838 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000839 }
840
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000841private:
842 /// Coerce the register to AFGR64 and return the real register for the current
843 /// target.
844 unsigned getAFGR64Reg() const {
845 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
846 if (RegIdx.Index % 2 != 0)
847 AsmParser.Warning(StartLoc, "Float register should be even.");
848 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
849 .getRegister(RegIdx.Index / 2);
850 }
851
852 /// Coerce the register to FGR64 and return the real register for the current
853 /// target.
854 unsigned getFGR64Reg() const {
855 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
856 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
857 .getRegister(RegIdx.Index);
858 }
859
860 /// Coerce the register to FGR32 and return the real register for the current
861 /// target.
862 unsigned getFGR32Reg() const {
863 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
864 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
865 .getRegister(RegIdx.Index);
866 }
867
868 /// Coerce the register to FGRH32 and return the real register for the current
869 /// target.
870 unsigned getFGRH32Reg() const {
871 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
872 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
873 .getRegister(RegIdx.Index);
874 }
875
876 /// Coerce the register to FCC and return the real register for the current
877 /// target.
878 unsigned getFCCReg() const {
879 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
880 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
881 .getRegister(RegIdx.Index);
882 }
883
884 /// Coerce the register to MSA128 and return the real register for the current
885 /// target.
886 unsigned getMSA128Reg() const {
887 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
888 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
889 // identical
890 unsigned ClassID = Mips::MSA128BRegClassID;
891 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
892 }
893
894 /// Coerce the register to MSACtrl and return the real register for the
895 /// current target.
896 unsigned getMSACtrlReg() const {
897 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
898 unsigned ClassID = Mips::MSACtrlRegClassID;
899 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
900 }
901
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000902 /// Coerce the register to COP0 and return the real register for the
903 /// current target.
904 unsigned getCOP0Reg() const {
905 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
906 unsigned ClassID = Mips::COP0RegClassID;
907 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
908 }
909
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000910 /// Coerce the register to COP2 and return the real register for the
911 /// current target.
912 unsigned getCOP2Reg() const {
913 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
914 unsigned ClassID = Mips::COP2RegClassID;
915 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
916 }
917
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000918 /// Coerce the register to COP3 and return the real register for the
919 /// current target.
920 unsigned getCOP3Reg() const {
921 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
922 unsigned ClassID = Mips::COP3RegClassID;
923 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
924 }
925
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000926 /// Coerce the register to ACC64DSP and return the real register for the
927 /// current target.
928 unsigned getACC64DSPReg() const {
929 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
930 unsigned ClassID = Mips::ACC64DSPRegClassID;
931 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
932 }
933
934 /// Coerce the register to HI32DSP and return the real register for the
935 /// current target.
936 unsigned getHI32DSPReg() const {
937 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
938 unsigned ClassID = Mips::HI32DSPRegClassID;
939 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
940 }
941
942 /// Coerce the register to LO32DSP and return the real register for the
943 /// current target.
944 unsigned getLO32DSPReg() const {
945 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
946 unsigned ClassID = Mips::LO32DSPRegClassID;
947 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
948 }
949
950 /// Coerce the register to CCR and return the real register for the
951 /// current target.
952 unsigned getCCRReg() const {
953 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
954 unsigned ClassID = Mips::CCRRegClassID;
955 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
956 }
957
958 /// Coerce the register to HWRegs and return the real register for the
959 /// current target.
960 unsigned getHWRegsReg() const {
961 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
962 unsigned ClassID = Mips::HWRegsRegClassID;
963 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
964 }
965
966public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000967 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000968 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000969 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000970 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000971 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000972 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000973 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000974 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000975 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000976
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000977 void addRegOperands(MCInst &Inst, unsigned N) const {
978 llvm_unreachable("Use a custom parser instead");
979 }
980
Daniel Sanders21bce302014-04-01 12:35:23 +0000981 /// Render the operand to an MCInst as a GPR32
982 /// Asserts if the wrong number of operands are requested, or the operand
983 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +0000984 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
985 assert(N == 1 && "Invalid number of operands!");
986 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
987 }
988
989 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
990 assert(N == 1 && "Invalid number of operands!");
991 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
992 }
993
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000994 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
995 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000996 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000997 }
998
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000999 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
1000 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001001 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001002 }
1003
Jozef Kolek1904fa22014-11-24 14:25:53 +00001004 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1005 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001006 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001007 }
1008
Zoran Jovanovic41688672015-02-10 16:36:20 +00001009 void addGPRMM16AsmRegMovePOperands(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(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001012 }
1013
Daniel Sanders21bce302014-04-01 12:35:23 +00001014 /// Render the operand to an MCInst as a GPR64
1015 /// Asserts if the wrong number of operands are requested, or the operand
1016 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001017 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1018 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001019 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001020 }
1021
1022 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1023 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001024 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001025 }
1026
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001027 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1028 assert(N == 1 && "Invalid number of operands!");
1029 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1030 }
1031
1032 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1033 assert(N == 1 && "Invalid number of operands!");
1034 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1035 }
1036
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001037 void addFGR64AsmRegOperands(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(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001040 }
1041
1042 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1043 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001044 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001045 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001046 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001047 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001048 AsmParser.getParser().printError(
1049 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1050 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001051 }
1052
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001053 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1054 assert(N == 1 && "Invalid number of operands!");
1055 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1056 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1057 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1058 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1059 "registers");
1060 }
1061
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001062 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1063 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001064 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001065 }
1066
1067 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1068 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001069 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001070 }
1071
1072 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1073 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001074 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001075 }
1076
1077 void addMSACtrlAsmRegOperands(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(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001080 }
1081
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001082 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1083 assert(N == 1 && "Invalid number of operands!");
1084 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1085 }
1086
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001087 void addCOP2AsmRegOperands(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(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001090 }
1091
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001092 void addCOP3AsmRegOperands(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(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001095 }
1096
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001097 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1098 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001099 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001100 }
1101
1102 void addHI32DSPAsmRegOperands(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(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 }
1106
1107 void addLO32DSPAsmRegOperands(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(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001110 }
1111
1112 void addCCRAsmRegOperands(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(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001115 }
1116
1117 void addHWRegsAsmRegOperands(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(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001120 }
1121
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001122 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001123 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1124 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001125 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001126 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001127 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001128 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001129 Inst.addOperand(MCOperand::createImm(Imm));
1130 }
1131
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001132 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001133 void addSImmOperands(MCInst &Inst, unsigned N) const {
1134 if (isImm() && !isConstantImm()) {
1135 addExpr(Inst, getImm());
1136 return;
1137 }
1138 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1139 }
1140
1141 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001142 void addUImmOperands(MCInst &Inst, unsigned N) const {
1143 if (isImm() && !isConstantImm()) {
1144 addExpr(Inst, getImm());
1145 return;
1146 }
1147 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1148 }
1149
Daniel Sanders78e89022016-03-11 11:37:50 +00001150 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1151 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1152 assert(N == 1 && "Invalid number of operands!");
1153 int64_t Imm = getConstantImm() - Offset;
1154 Imm = SignExtend64<Bits>(Imm);
1155 Imm += Offset;
1156 Imm += AdjustOffset;
1157 Inst.addOperand(MCOperand::createImm(Imm));
1158 }
1159
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001160 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001161 assert(N == 1 && "Invalid number of operands!");
1162 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001163 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001164 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001165
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001166 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001167 assert(N == 2 && "Invalid number of operands!");
1168
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001169 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1170 ? getMemBase()->getGPR64Reg()
1171 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001172
1173 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001174 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001175 }
1176
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001177 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1178 assert(N == 2 && "Invalid number of operands!");
1179
Jim Grosbache9119e42015-05-13 18:37:00 +00001180 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001181
1182 const MCExpr *Expr = getMemOff();
1183 addExpr(Inst, Expr);
1184 }
1185
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001186 void addRegListOperands(MCInst &Inst, unsigned N) const {
1187 assert(N == 1 && "Invalid number of operands!");
1188
1189 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001190 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001191 }
1192
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001193 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1194 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001195 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001196 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001197 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1198 Inst.addOperand(MCOperand::createReg(
1199 RegIdx.RegInfo->getRegClass(
1200 AsmParser.getABI().AreGprs64bit()
1201 ? Mips::GPR64RegClassID
1202 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1203 Inst.addOperand(MCOperand::createReg(
1204 RegIdx.RegInfo->getRegClass(
1205 AsmParser.getABI().AreGprs64bit()
1206 ? Mips::GPR64RegClassID
1207 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001208 }
1209
Zoran Jovanovic41688672015-02-10 16:36:20 +00001210 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1211 assert(N == 2 && "Invalid number of operands!");
1212 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001213 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001214 }
1215
Craig Topper56c590a2014-04-29 07:58:02 +00001216 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001217 // As a special case until we sort out the definition of div/divu, accept
1218 // $0/$zero here so that MCK_ZERO works correctly.
1219 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001220 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001221
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001222 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001223 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001224
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001225 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001226 int64_t Res;
1227 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001228 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001229
Daniel Sanders52da7af2015-11-06 12:11:03 +00001230 bool isConstantImmz() const {
1231 return isConstantImm() && getConstantImm() == 0;
1232 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001233
Daniel Sandersea4f6532015-11-06 12:22:31 +00001234 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1235 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1236 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001237
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001238 template <unsigned Bits> bool isSImm() const {
1239 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1240 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001241
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001242 template <unsigned Bits> bool isUImm() const {
1243 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1244 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001245
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001246 template <unsigned Bits> bool isAnyImm() const {
1247 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1248 isUInt<Bits>(getConstantImm()))
1249 : isImm();
1250 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001251
Daniel Sanders78e89022016-03-11 11:37:50 +00001252 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1253 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001254 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001255
Hrvoje Varga46458d02016-02-25 12:53:29 +00001256 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1257 return isConstantImm() && getConstantImm() >= Bottom &&
1258 getConstantImm() <= Top;
1259 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001260
Craig Topper56c590a2014-04-29 07:58:02 +00001261 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001262 // Note: It's not possible to pretend that other operand kinds are tokens.
1263 // The matcher emitter checks tokens first.
1264 return Kind == k_Token;
1265 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001266
Craig Topper56c590a2014-04-29 07:58:02 +00001267 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001268
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001269 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001270 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001271 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001272
Simon Dardis4ccda502016-05-27 13:56:36 +00001273 // Allow relocation operators.
1274 // FIXME: This predicate and others need to look through binary expressions
1275 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001276 template <unsigned Bits, unsigned ShiftAmount = 0>
1277 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001278 if (!isMem())
1279 return false;
1280 if (!getMemBase()->isGPRAsmReg())
1281 return false;
1282 if (isa<MCTargetExpr>(getMemOff()) ||
1283 (isConstantMemOff() &&
1284 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1285 return true;
1286 MCValue Res;
1287 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1288 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001289 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001290
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001291 bool isMemWithGRPMM16Base() const {
1292 return isMem() && getMemBase()->isMM16AsmReg();
1293 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001294
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001295 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1296 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1297 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1298 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001299
Jozef Kolek12c69822014-12-23 16:16:33 +00001300 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1301 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1302 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1303 && (getMemBase()->getGPR32Reg() == Mips::SP);
1304 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001305
Daniel Sanderse473dc92016-05-09 13:38:25 +00001306 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1307 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1308 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1309 && (getMemBase()->getGPR32Reg() == Mips::GP);
1310 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001311
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001312 template <unsigned Bits, unsigned ShiftLeftAmount>
1313 bool isScaledUImm() const {
1314 return isConstantImm() &&
1315 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001316 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001317
Daniel Sanders97297772016-03-22 14:40:00 +00001318 template <unsigned Bits, unsigned ShiftLeftAmount>
1319 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001320 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1321 return true;
1322 // Operand can also be a symbol or symbol plus offset in case of relocations.
1323 if (Kind != k_Immediate)
1324 return false;
1325 MCValue Res;
1326 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1327 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001328 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001329
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001330 bool isRegList16() const {
1331 if (!isRegList())
1332 return false;
1333
1334 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001335 if (Size < 2 || Size > 5)
1336 return false;
1337
1338 unsigned R0 = RegList.List->front();
1339 unsigned R1 = RegList.List->back();
1340 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1341 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001342 return false;
1343
1344 int PrevReg = *RegList.List->begin();
1345 for (int i = 1; i < Size - 1; i++) {
1346 int Reg = (*(RegList.List))[i];
1347 if ( Reg != PrevReg + 1)
1348 return false;
1349 PrevReg = Reg;
1350 }
1351
1352 return true;
1353 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001354
Vladimir Medic2b953d02013-10-01 09:48:56 +00001355 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001356
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001357 bool isLSAImm() const {
1358 if (!isConstantImm())
1359 return false;
1360 int64_t Val = getConstantImm();
1361 return 1 <= Val && Val <= 4;
1362 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001363
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001364 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001365
Zoran Jovanovic41688672015-02-10 16:36:20 +00001366 bool isMovePRegPair() const {
1367 if (Kind != k_RegList || RegList.List->size() != 2)
1368 return false;
1369
1370 unsigned R0 = RegList.List->front();
1371 unsigned R1 = RegList.List->back();
1372
1373 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1374 (R0 == Mips::A1 && R1 == Mips::A3) ||
1375 (R0 == Mips::A2 && R1 == Mips::A3) ||
1376 (R0 == Mips::A0 && R1 == Mips::S5) ||
1377 (R0 == Mips::A0 && R1 == Mips::S6) ||
1378 (R0 == Mips::A0 && R1 == Mips::A1) ||
1379 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001380 (R0 == Mips::A0 && R1 == Mips::A3) ||
1381 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1382 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1383 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1384 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1385 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1386 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1387 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1388 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001389 return true;
1390
1391 return false;
1392 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001393
1394 StringRef getToken() const {
1395 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001396 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001397 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001398
Zlatko Buljanba553a62016-05-09 08:07:28 +00001399 bool isRegPair() const {
1400 return Kind == k_RegPair && RegIdx.Index <= 30;
1401 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001402
Craig Topper56c590a2014-04-29 07:58:02 +00001403 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001404 // As a special case until we sort out the definition of div/divu, accept
1405 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001406 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1407 RegIdx.Kind & RegKind_GPR)
1408 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001409
Daniel Sanders976d9382016-07-05 13:38:40 +00001410 llvm_unreachable("Invalid access!");
1411 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001412 }
1413
Jack Carterb4dbc172012-09-05 23:34:03 +00001414 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001415 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001416 return Imm.Val;
1417 }
1418
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001419 int64_t getConstantImm() const {
1420 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001421 int64_t Value = 0;
1422 (void)Val->evaluateAsAbsolute(Value);
1423 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001424 }
1425
1426 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001427 assert((Kind == k_Memory) && "Invalid access!");
1428 return Mem.Base;
1429 }
1430
1431 const MCExpr *getMemOff() const {
1432 assert((Kind == k_Memory) && "Invalid access!");
1433 return Mem.Off;
1434 }
1435
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001436 int64_t getConstantMemOff() const {
1437 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1438 }
1439
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001440 const SmallVectorImpl<unsigned> &getRegList() const {
1441 assert((Kind == k_RegList) && "Invalid access!");
1442 return *(RegList.List);
1443 }
1444
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001445 unsigned getRegPair() const {
1446 assert((Kind == k_RegPair) && "Invalid access!");
1447 return RegIdx.Index;
1448 }
1449
David Blaikie960ea3f2014-06-08 16:18:35 +00001450 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1451 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001452 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001453 Op->Tok.Data = Str.data();
1454 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001455 Op->StartLoc = S;
1456 Op->EndLoc = S;
1457 return Op;
1458 }
1459
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001460 /// Create a numeric register (e.g. $1). The exact register remains
1461 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001462 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001463 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1464 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001465 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001466 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001467 }
1468
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001469 /// Create a register that is definitely a GPR.
1470 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001471 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001472 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1473 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1474 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001475 }
1476
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001477 /// Create a register that is definitely a FGR.
1478 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001479 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001480 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1481 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1482 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001483 }
1484
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001485 /// Create a register that is definitely a HWReg.
1486 /// This is typically only used for named registers such as $hwr_cpunum.
1487 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001488 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001489 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001490 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001491 }
1492
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001493 /// Create a register that is definitely an FCC.
1494 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001495 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001496 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1497 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1498 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001499 }
1500
1501 /// Create a register that is definitely an ACC.
1502 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001503 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001504 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1505 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1506 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001507 }
1508
1509 /// Create a register that is definitely an MSA128.
1510 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001511 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001512 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1513 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1514 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001515 }
1516
1517 /// Create a register that is definitely an MSACtrl.
1518 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001519 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001520 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1521 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1522 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001523 }
1524
David Blaikie960ea3f2014-06-08 16:18:35 +00001525 static std::unique_ptr<MipsOperand>
1526 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001527 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001528 Op->Imm.Val = Val;
1529 Op->StartLoc = S;
1530 Op->EndLoc = E;
1531 return Op;
1532 }
1533
David Blaikie960ea3f2014-06-08 16:18:35 +00001534 static std::unique_ptr<MipsOperand>
1535 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1536 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001537 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001538 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001539 Op->Mem.Off = Off;
1540 Op->StartLoc = S;
1541 Op->EndLoc = E;
1542 return Op;
1543 }
1544
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001545 static std::unique_ptr<MipsOperand>
1546 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1547 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001548 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001549
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001550 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001551 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001552 Op->StartLoc = StartLoc;
1553 Op->EndLoc = EndLoc;
1554 return Op;
1555 }
1556
Daniel Sandersd044e492016-05-09 13:10:57 +00001557 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1558 SMLoc S, SMLoc E,
1559 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001560 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001561 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001562 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1563 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001564 Op->StartLoc = S;
1565 Op->EndLoc = E;
1566 return Op;
1567 }
1568
Simon Dardis509da1a2017-02-13 16:06:48 +00001569 bool isGPRZeroAsmReg() const {
1570 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1571 }
1572
1573 bool isGPRNonZeroAsmReg() const {
1574 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1575 RegIdx.Index <= 31;
1576 }
1577
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001578 bool isGPRAsmReg() const {
1579 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001580 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001581
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001582 bool isMM16AsmReg() const {
1583 if (!(isRegIdx() && RegIdx.Kind))
1584 return false;
1585 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1586 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001587
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001588 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001589 bool isMM16AsmRegZero() const {
1590 if (!(isRegIdx() && RegIdx.Kind))
1591 return false;
1592 return (RegIdx.Index == 0 ||
1593 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1594 RegIdx.Index == 17);
1595 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001596
Zoran Jovanovic41688672015-02-10 16:36:20 +00001597 bool isMM16AsmRegMoveP() const {
1598 if (!(isRegIdx() && RegIdx.Kind))
1599 return false;
1600 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1601 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1602 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001603
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001604 bool isFGRAsmReg() const {
1605 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1606 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001607 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001608
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001609 bool isStrictlyFGRAsmReg() const {
1610 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1611 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1612 }
1613
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001614 bool isHWRegsAsmReg() const {
1615 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001616 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001617
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001618 bool isCCRAsmReg() const {
1619 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001620 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001621
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001622 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001623 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1624 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001625 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001626 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001627
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001628 bool isACCAsmReg() const {
1629 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001630 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001631
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001632 bool isCOP0AsmReg() const {
1633 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1634 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001635
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001636 bool isCOP2AsmReg() const {
1637 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001638 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001639
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001640 bool isCOP3AsmReg() const {
1641 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1642 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001643
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001644 bool isMSA128AsmReg() const {
1645 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001646 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001647
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001648 bool isMSACtrlAsmReg() const {
1649 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001650 }
1651
Jack Carterb4dbc172012-09-05 23:34:03 +00001652 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001653 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001654 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001655 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001656
Craig Topper56c590a2014-04-29 07:58:02 +00001657 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001658 switch (Kind) {
1659 case k_Immediate:
1660 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001661 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001662 OS << ">";
1663 break;
1664 case k_Memory:
1665 OS << "Mem<";
1666 Mem.Base->print(OS);
1667 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001668 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001669 OS << ">";
1670 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001671 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001672 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1673 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001674 break;
1675 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001676 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001677 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001678 case k_RegList:
1679 OS << "RegList< ";
1680 for (auto Reg : (*RegList.List))
1681 OS << Reg << " ";
1682 OS << ">";
1683 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001684 case k_RegPair:
1685 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1686 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001687 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001688 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001689
1690 bool isValidForTie(const MipsOperand &Other) const {
1691 if (Kind != Other.Kind)
1692 return false;
1693
1694 switch (Kind) {
1695 default:
1696 llvm_unreachable("Unexpected kind");
1697 return false;
1698 case k_RegisterIndex: {
1699 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1700 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1701 return Token == OtherToken;
1702 }
1703 }
1704 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001705}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001706
1707} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001708
Jack Carter9e65aa32013-03-22 00:05:30 +00001709namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001710
Jack Carter9e65aa32013-03-22 00:05:30 +00001711extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001712
1713} // end namespace llvm
1714
Jack Carter9e65aa32013-03-22 00:05:30 +00001715static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1716 return MipsInsts[Opcode];
1717}
1718
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001719static bool hasShortDelaySlot(unsigned Opcode) {
1720 switch (Opcode) {
1721 case Mips::JALS_MM:
1722 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001723 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001724 case Mips::BGEZALS_MM:
1725 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001726 return true;
1727 default:
1728 return false;
1729 }
1730}
1731
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001732static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1733 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1734 return &SRExpr->getSymbol();
1735 }
1736
1737 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1738 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1739 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1740
1741 if (LHSSym)
1742 return LHSSym;
1743
1744 if (RHSSym)
1745 return RHSSym;
1746
1747 return nullptr;
1748 }
1749
1750 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1751 return getSingleMCSymbol(UExpr->getSubExpr());
1752
1753 return nullptr;
1754}
1755
1756static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1757 if (isa<MCSymbolRefExpr>(Expr))
1758 return 1;
1759
1760 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1761 return countMCSymbolRefExpr(BExpr->getLHS()) +
1762 countMCSymbolRefExpr(BExpr->getRHS());
1763
1764 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1765 return countMCSymbolRefExpr(UExpr->getSubExpr());
1766
1767 return 0;
1768}
1769
Jack Carter9e65aa32013-03-22 00:05:30 +00001770bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001771 MCStreamer &Out,
1772 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001773 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001774 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001775 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001776
Jack Carter9e65aa32013-03-22 00:05:30 +00001777 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001778
1779 if (MCID.isBranch() || MCID.isCall()) {
1780 const unsigned Opcode = Inst.getOpcode();
1781 MCOperand Offset;
1782
1783 switch (Opcode) {
1784 default:
1785 break;
Kai Nackee0245392015-01-27 19:11:28 +00001786 case Mips::BBIT0:
1787 case Mips::BBIT032:
1788 case Mips::BBIT1:
1789 case Mips::BBIT132:
1790 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001791 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001792
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001793 case Mips::BEQ:
1794 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001795 case Mips::BEQ_MM:
1796 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001797 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001798 Offset = Inst.getOperand(2);
1799 if (!Offset.isImm())
1800 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001801 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001802 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001803 if (OffsetToAlignment(Offset.getImm(),
1804 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001805 return Error(IDLoc, "branch to misaligned address");
1806 break;
1807 case Mips::BGEZ:
1808 case Mips::BGTZ:
1809 case Mips::BLEZ:
1810 case Mips::BLTZ:
1811 case Mips::BGEZAL:
1812 case Mips::BLTZAL:
1813 case Mips::BC1F:
1814 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001815 case Mips::BGEZ_MM:
1816 case Mips::BGTZ_MM:
1817 case Mips::BLEZ_MM:
1818 case Mips::BLTZ_MM:
1819 case Mips::BGEZAL_MM:
1820 case Mips::BLTZAL_MM:
1821 case Mips::BC1F_MM:
1822 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001823 case Mips::BC1EQZC_MMR6:
1824 case Mips::BC1NEZC_MMR6:
1825 case Mips::BC2EQZC_MMR6:
1826 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001827 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001828 Offset = Inst.getOperand(1);
1829 if (!Offset.isImm())
1830 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001831 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001832 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001833 if (OffsetToAlignment(Offset.getImm(),
1834 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001835 return Error(IDLoc, "branch to misaligned address");
1836 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001837 case Mips::BGEC: case Mips::BGEC_MMR6:
1838 case Mips::BLTC: case Mips::BLTC_MMR6:
1839 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1840 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1841 case Mips::BEQC: case Mips::BEQC_MMR6:
1842 case Mips::BNEC: case Mips::BNEC_MMR6:
1843 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1844 Offset = Inst.getOperand(2);
1845 if (!Offset.isImm())
1846 break; // We'll deal with this situation later on when applying fixups.
1847 if (!isIntN(18, Offset.getImm()))
1848 return Error(IDLoc, "branch target out of range");
1849 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1850 return Error(IDLoc, "branch to misaligned address");
1851 break;
1852 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1853 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1854 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1855 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1856 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1857 Offset = Inst.getOperand(1);
1858 if (!Offset.isImm())
1859 break; // We'll deal with this situation later on when applying fixups.
1860 if (!isIntN(18, Offset.getImm()))
1861 return Error(IDLoc, "branch target out of range");
1862 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1863 return Error(IDLoc, "branch to misaligned address");
1864 break;
1865 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1866 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1867 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1868 Offset = Inst.getOperand(1);
1869 if (!Offset.isImm())
1870 break; // We'll deal with this situation later on when applying fixups.
1871 if (!isIntN(23, Offset.getImm()))
1872 return Error(IDLoc, "branch target out of range");
1873 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1874 return Error(IDLoc, "branch to misaligned address");
1875 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001876 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001877 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001878 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001879 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001880 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1881 Offset = Inst.getOperand(1);
1882 if (!Offset.isImm())
1883 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001884 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001885 return Error(IDLoc, "branch target out of range");
1886 if (OffsetToAlignment(Offset.getImm(), 2LL))
1887 return Error(IDLoc, "branch to misaligned address");
1888 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001889 }
1890 }
1891
Daniel Sandersa84989a2014-06-16 13:25:35 +00001892 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1893 // We still accept it but it is a normal nop.
1894 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1895 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1896 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1897 "nop instruction");
1898 }
1899
Kai Nackee0245392015-01-27 19:11:28 +00001900 if (hasCnMips()) {
1901 const unsigned Opcode = Inst.getOpcode();
1902 MCOperand Opnd;
1903 int Imm;
1904
1905 switch (Opcode) {
1906 default:
1907 break;
1908
1909 case Mips::BBIT0:
1910 case Mips::BBIT032:
1911 case Mips::BBIT1:
1912 case Mips::BBIT132:
1913 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1914 // The offset is handled above
1915 Opnd = Inst.getOperand(1);
1916 if (!Opnd.isImm())
1917 return Error(IDLoc, "expected immediate operand kind");
1918 Imm = Opnd.getImm();
1919 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1920 Opcode == Mips::BBIT1 ? 63 : 31))
1921 return Error(IDLoc, "immediate operand value out of range");
1922 if (Imm > 31) {
1923 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1924 : Mips::BBIT132);
1925 Inst.getOperand(1).setImm(Imm - 32);
1926 }
1927 break;
1928
Kai Nackee0245392015-01-27 19:11:28 +00001929 case Mips::SEQi:
1930 case Mips::SNEi:
1931 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1932 Opnd = Inst.getOperand(2);
1933 if (!Opnd.isImm())
1934 return Error(IDLoc, "expected immediate operand kind");
1935 Imm = Opnd.getImm();
1936 if (!isInt<10>(Imm))
1937 return Error(IDLoc, "immediate operand value out of range");
1938 break;
1939 }
1940 }
1941
Simon Dardis509da1a2017-02-13 16:06:48 +00001942 // Warn on division by zero. We're checking here as all instructions get
1943 // processed here, not just the macros that need expansion.
1944 //
1945 // The MIPS backend models most of the divison instructions and macros as
1946 // three operand instructions. The pre-R6 divide instructions however have
1947 // two operands and explicitly define HI/LO as part of the instruction,
1948 // not in the operands.
1949 unsigned FirstOp = 1;
1950 unsigned SecondOp = 2;
1951 switch (Inst.getOpcode()) {
1952 default:
1953 break;
1954 case Mips::SDivIMacro:
1955 case Mips::UDivIMacro:
1956 case Mips::DSDivIMacro:
1957 case Mips::DUDivIMacro:
1958 if (Inst.getOperand(2).getImm() == 0) {
1959 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1960 Inst.getOperand(1).getReg() == Mips::ZERO_64)
1961 Warning(IDLoc, "dividing zero by zero");
1962 else
1963 Warning(IDLoc, "division by zero");
1964 }
1965 break;
1966 case Mips::DSDIV:
1967 case Mips::SDIV:
1968 case Mips::UDIV:
1969 case Mips::DUDIV:
1970 case Mips::UDIV_MM:
1971 case Mips::SDIV_MM:
1972 FirstOp = 0;
1973 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00001974 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00001975 case Mips::SDivMacro:
1976 case Mips::DSDivMacro:
1977 case Mips::UDivMacro:
1978 case Mips::DUDivMacro:
1979 case Mips::DIV:
1980 case Mips::DIVU:
1981 case Mips::DDIV:
1982 case Mips::DDIVU:
1983 case Mips::DIVU_MMR6:
1984 case Mips::DDIVU_MM64R6:
1985 case Mips::DIV_MMR6:
1986 case Mips::DDIV_MM64R6:
1987 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
1988 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
1989 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
1990 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
1991 Warning(IDLoc, "dividing zero by zero");
1992 else
1993 Warning(IDLoc, "division by zero");
1994 }
1995 break;
1996 }
1997
Simon Atanasyan50485142016-12-12 17:40:26 +00001998 // For PIC code convert unconditional jump to unconditional branch.
1999 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
2000 inPicMode()) {
2001 MCInst BInst;
2002 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
2003 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2004 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2005 BInst.addOperand(Inst.getOperand(0));
2006 Inst = BInst;
2007 }
2008
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002009 // This expansion is not in a function called by tryExpandInstruction()
2010 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002011 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2012 inPicMode()) {
2013 warnIfNoMacro(IDLoc);
2014
2015 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2016
2017 // We can do this expansion if there's only 1 symbol in the argument
2018 // expression.
2019 if (countMCSymbolRefExpr(JalExpr) > 1)
2020 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2021
2022 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002023 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002024 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2025
2026 // FIXME: Add support for label+offset operands (currently causes an error).
2027 // FIXME: Add support for forward-declared local symbols.
2028 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002029 if (JalSym->isInSection() || JalSym->isTemporary() ||
2030 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002031 if (isABI_O32()) {
2032 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002033 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002034 // R_(MICRO)MIPS_GOT16 label
2035 // addiu $25, $25, 0
2036 // R_(MICRO)MIPS_LO16 label
2037 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002038 const MCExpr *Got16RelocExpr =
2039 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2040 const MCExpr *Lo16RelocExpr =
2041 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002042
Daniel Sandersa736b372016-04-29 13:33:12 +00002043 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2044 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2045 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2046 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002047 } else if (isABI_N32() || isABI_N64()) {
2048 // If it's a local symbol and the N32/N64 ABIs are being used,
2049 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002050 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002051 // R_(MICRO)MIPS_GOT_DISP label
2052 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002053 const MCExpr *GotDispRelocExpr =
2054 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002055
Daniel Sandersa736b372016-04-29 13:33:12 +00002056 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2057 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2058 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002059 }
2060 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002061 // If it's an external/weak symbol, we expand to:
2062 // lw/ld $25, 0($gp)
2063 // R_(MICRO)MIPS_CALL16 label
2064 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002065 const MCExpr *Call16RelocExpr =
2066 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002067
Daniel Sandersa736b372016-04-29 13:33:12 +00002068 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2069 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002070 }
2071
2072 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002073 if (IsCpRestoreSet && inMicroMipsMode())
2074 JalrInst.setOpcode(Mips::JALRS_MM);
2075 else
2076 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002077 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2078 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2079
2080 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2081 // This relocation is supposed to be an optimization hint for the linker
2082 // and is not necessary for correctness.
2083
2084 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002085 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002086 }
2087
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002088 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2089 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002090 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002091 // reference or immediate we may have to expand instructions.
2092 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002093 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002094 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2095 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002096 MCOperand &Op = Inst.getOperand(i);
2097 if (Op.isImm()) {
2098 int MemOffset = Op.getImm();
2099 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002100 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002101 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00002102 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002103 }
2104 } else if (Op.isExpr()) {
2105 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002106 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002107 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002108 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002109 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002110 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002111 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002112 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002113 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002114 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002115 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002116 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002117 }
2118 }
2119 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002120 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002121 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002122
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002123 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002124 if (MCID.mayLoad()) {
2125 // Try to create 16-bit GP relative load instruction.
2126 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2127 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2128 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2129 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2130 MCOperand &Op = Inst.getOperand(i);
2131 if (Op.isImm()) {
2132 int MemOffset = Op.getImm();
2133 MCOperand &DstReg = Inst.getOperand(0);
2134 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002135 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002136 getContext().getRegisterInfo()->getRegClass(
2137 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002138 (BaseReg.getReg() == Mips::GP ||
2139 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002140
Daniel Sandersa736b372016-04-29 13:33:12 +00002141 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2142 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002143 return false;
2144 }
2145 }
2146 }
2147 } // for
2148 } // if load
2149
2150 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2151
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002152 MCOperand Opnd;
2153 int Imm;
2154
2155 switch (Inst.getOpcode()) {
2156 default:
2157 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002158 case Mips::ADDIUSP_MM:
2159 Opnd = Inst.getOperand(0);
2160 if (!Opnd.isImm())
2161 return Error(IDLoc, "expected immediate operand kind");
2162 Imm = Opnd.getImm();
2163 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2164 Imm % 4 != 0)
2165 return Error(IDLoc, "immediate operand value out of range");
2166 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002167 case Mips::SLL16_MM:
2168 case Mips::SRL16_MM:
2169 Opnd = Inst.getOperand(2);
2170 if (!Opnd.isImm())
2171 return Error(IDLoc, "expected immediate operand kind");
2172 Imm = Opnd.getImm();
2173 if (Imm < 1 || Imm > 8)
2174 return Error(IDLoc, "immediate operand value out of range");
2175 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002176 case Mips::LI16_MM:
2177 Opnd = Inst.getOperand(1);
2178 if (!Opnd.isImm())
2179 return Error(IDLoc, "expected immediate operand kind");
2180 Imm = Opnd.getImm();
2181 if (Imm < -1 || Imm > 126)
2182 return Error(IDLoc, "immediate operand value out of range");
2183 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002184 case Mips::ADDIUR2_MM:
2185 Opnd = Inst.getOperand(2);
2186 if (!Opnd.isImm())
2187 return Error(IDLoc, "expected immediate operand kind");
2188 Imm = Opnd.getImm();
2189 if (!(Imm == 1 || Imm == -1 ||
2190 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2191 return Error(IDLoc, "immediate operand value out of range");
2192 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002193 case Mips::ANDI16_MM:
2194 Opnd = Inst.getOperand(2);
2195 if (!Opnd.isImm())
2196 return Error(IDLoc, "expected immediate operand kind");
2197 Imm = Opnd.getImm();
2198 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2199 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2200 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2201 return Error(IDLoc, "immediate operand value out of range");
2202 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002203 case Mips::LBU16_MM:
2204 Opnd = Inst.getOperand(2);
2205 if (!Opnd.isImm())
2206 return Error(IDLoc, "expected immediate operand kind");
2207 Imm = Opnd.getImm();
2208 if (Imm < -1 || Imm > 14)
2209 return Error(IDLoc, "immediate operand value out of range");
2210 break;
2211 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002212 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002213 Opnd = Inst.getOperand(2);
2214 if (!Opnd.isImm())
2215 return Error(IDLoc, "expected immediate operand kind");
2216 Imm = Opnd.getImm();
2217 if (Imm < 0 || Imm > 15)
2218 return Error(IDLoc, "immediate operand value out of range");
2219 break;
2220 case Mips::LHU16_MM:
2221 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002222 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002223 Opnd = Inst.getOperand(2);
2224 if (!Opnd.isImm())
2225 return Error(IDLoc, "expected immediate operand kind");
2226 Imm = Opnd.getImm();
2227 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2228 return Error(IDLoc, "immediate operand value out of range");
2229 break;
2230 case Mips::LW16_MM:
2231 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002232 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002233 Opnd = Inst.getOperand(2);
2234 if (!Opnd.isImm())
2235 return Error(IDLoc, "expected immediate operand kind");
2236 Imm = Opnd.getImm();
2237 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2238 return Error(IDLoc, "immediate operand value out of range");
2239 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002240 case Mips::ADDIUPC_MM:
2241 MCOperand Opnd = Inst.getOperand(1);
2242 if (!Opnd.isImm())
2243 return Error(IDLoc, "expected immediate operand kind");
2244 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002245 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002246 return Error(IDLoc, "immediate operand value out of range");
2247 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002248 }
2249 }
2250
Daniel Sandersd8c07762016-04-18 12:35:36 +00002251 bool FillDelaySlot =
2252 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2253 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002254 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002255
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002256 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002257 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002258 switch (ExpandResult) {
2259 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002260 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002261 break;
2262 case MER_Success:
2263 break;
2264 case MER_Fail:
2265 return true;
2266 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002267
Daniel Sanderscda908a2016-05-16 09:10:13 +00002268 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2269 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2270 if (inMicroMipsMode())
2271 TOut.setUsesMicroMips();
2272
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002273 // If this instruction has a delay slot and .set reorder is active,
2274 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002275 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002276 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2277 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002278 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002279
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002280 if ((Inst.getOpcode() == Mips::JalOneReg ||
2281 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2282 isPicAndNotNxxAbi()) {
2283 if (IsCpRestoreSet) {
2284 // We need a NOP between the JALR and the LW:
2285 // If .set reorder has been used, we've already emitted a NOP.
2286 // If .set noreorder has been used, we need to emit a NOP at this point.
2287 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002288 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2289 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002290
2291 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002292 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002293 } else
2294 Warning(IDLoc, "no .cprestore used in PIC mode");
2295 }
2296
Jack Carter9e65aa32013-03-22 00:05:30 +00002297 return false;
2298}
2299
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002300MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002301MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2302 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002303 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002304 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002305 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002306 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002307 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002308 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002309 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002310 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002311 case Mips::LoadAddrImm64:
2312 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2313 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2314 "expected immediate operand kind");
2315
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002316 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2317 Inst.getOperand(1),
2318 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002319 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002320 ? MER_Fail
2321 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002322 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002323 case Mips::LoadAddrReg64:
2324 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2325 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2326 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2327 "expected immediate operand kind");
2328
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002329 return expandLoadAddress(Inst.getOperand(0).getReg(),
2330 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2331 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002332 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002333 ? MER_Fail
2334 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002335 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002336 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002337 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2338 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002339 case Mips::SWM_MM:
2340 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002341 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2342 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002343 case Mips::JalOneReg:
2344 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002345 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002346 case Mips::BneImm:
2347 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002348 case Mips::BEQLImmMacro:
2349 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002350 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002351 case Mips::BLT:
2352 case Mips::BLE:
2353 case Mips::BGE:
2354 case Mips::BGT:
2355 case Mips::BLTU:
2356 case Mips::BLEU:
2357 case Mips::BGEU:
2358 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002359 case Mips::BLTL:
2360 case Mips::BLEL:
2361 case Mips::BGEL:
2362 case Mips::BGTL:
2363 case Mips::BLTUL:
2364 case Mips::BLEUL:
2365 case Mips::BGEUL:
2366 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002367 case Mips::BLTImmMacro:
2368 case Mips::BLEImmMacro:
2369 case Mips::BGEImmMacro:
2370 case Mips::BGTImmMacro:
2371 case Mips::BLTUImmMacro:
2372 case Mips::BLEUImmMacro:
2373 case Mips::BGEUImmMacro:
2374 case Mips::BGTUImmMacro:
2375 case Mips::BLTLImmMacro:
2376 case Mips::BLELImmMacro:
2377 case Mips::BGELImmMacro:
2378 case Mips::BGTLImmMacro:
2379 case Mips::BLTULImmMacro:
2380 case Mips::BLEULImmMacro:
2381 case Mips::BGEULImmMacro:
2382 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002383 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002384 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002385 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002386 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2387 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002388 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002389 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002390 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2391 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002392 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002393 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002394 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2395 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002396 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002397 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002398 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2399 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002400 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002401 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2402 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002403 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002404 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002405 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002406 case Mips::PseudoTRUNC_W_D:
2407 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2408 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002409
2410 case Mips::LoadImmSingleGPR:
2411 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2412 ? MER_Fail
2413 : MER_Success;
2414 case Mips::LoadImmSingleFGR:
2415 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2416 ? MER_Fail
2417 : MER_Success;
2418 case Mips::LoadImmDoubleGPR:
2419 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2420 ? MER_Fail
2421 : MER_Success;
2422 case Mips::LoadImmDoubleFGR:
2423 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2424 ? MER_Fail
2425 : MER_Success;
2426 case Mips::LoadImmDoubleFGR_32:
2427 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2428 ? MER_Fail
2429 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002430 case Mips::Ulh:
2431 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2432 case Mips::Ulhu:
2433 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002434 case Mips::Ush:
2435 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002436 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002437 case Mips::Usw:
2438 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002439 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002440 case Mips::NORImm64:
2441 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2442 case Mips::SLTImm64:
2443 if (isInt<16>(Inst.getOperand(2).getImm())) {
2444 Inst.setOpcode(Mips::SLTi64);
2445 return MER_NotAMacro;
2446 }
2447 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2448 case Mips::SLTUImm64:
2449 if (isInt<16>(Inst.getOperand(2).getImm())) {
2450 Inst.setOpcode(Mips::SLTiu64);
2451 return MER_NotAMacro;
2452 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002453 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002454 case Mips::ADDi: case Mips::ADDi_MM:
2455 case Mips::ADDiu: case Mips::ADDiu_MM:
2456 case Mips::SLTi: case Mips::SLTi_MM:
2457 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002458 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2459 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2460 int64_t ImmValue = Inst.getOperand(2).getImm();
2461 if (isInt<16>(ImmValue))
2462 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002463 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2464 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002465 }
2466 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002467 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2468 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2469 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002470 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2471 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2472 int64_t ImmValue = Inst.getOperand(2).getImm();
2473 if (isUInt<16>(ImmValue))
2474 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002475 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2476 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002477 }
2478 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002479 case Mips::ROL:
2480 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002481 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002482 case Mips::ROLImm:
2483 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002484 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002485 case Mips::DROL:
2486 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002487 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002488 case Mips::DROLImm:
2489 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002490 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002491 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002492 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002493 case Mips::MULImmMacro:
2494 case Mips::DMULImmMacro:
2495 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2496 case Mips::MULOMacro:
2497 case Mips::DMULOMacro:
2498 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2499 case Mips::MULOUMacro:
2500 case Mips::DMULOUMacro:
2501 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2502 case Mips::DMULMacro:
2503 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002504 case Mips::LDMacro:
2505 case Mips::SDMacro:
2506 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2507 Inst.getOpcode() == Mips::LDMacro)
2508 ? MER_Fail
2509 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002510 case Mips::SEQMacro:
2511 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2512 case Mips::SEQIMacro:
2513 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002514 }
Jack Carter30a59822012-10-04 04:03:53 +00002515}
Jack Carter92995f12012-10-06 00:53:28 +00002516
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002517bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002518 MCStreamer &Out,
2519 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002520 MipsTargetStreamer &TOut = getTargetStreamer();
2521
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002522 // Create a JALR instruction which is going to replace the pseudo-JAL.
2523 MCInst JalrInst;
2524 JalrInst.setLoc(IDLoc);
2525 const MCOperand FirstRegOp = Inst.getOperand(0);
2526 const unsigned Opcode = Inst.getOpcode();
2527
2528 if (Opcode == Mips::JalOneReg) {
2529 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002530 if (IsCpRestoreSet && inMicroMipsMode()) {
2531 JalrInst.setOpcode(Mips::JALRS16_MM);
2532 JalrInst.addOperand(FirstRegOp);
2533 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002534 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002535 JalrInst.addOperand(FirstRegOp);
2536 } else {
2537 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002538 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002539 JalrInst.addOperand(FirstRegOp);
2540 }
2541 } else if (Opcode == Mips::JalTwoReg) {
2542 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002543 if (IsCpRestoreSet && inMicroMipsMode())
2544 JalrInst.setOpcode(Mips::JALRS_MM);
2545 else
2546 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002547 JalrInst.addOperand(FirstRegOp);
2548 const MCOperand SecondRegOp = Inst.getOperand(1);
2549 JalrInst.addOperand(SecondRegOp);
2550 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002551 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002552
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002553 // If .set reorder is active and branch instruction has a delay slot,
2554 // emit a NOP after it.
2555 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002556 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2557 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2558 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002559
2560 return false;
2561}
2562
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002563/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002564template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002565 unsigned BitNum = findFirstSet(x);
2566
2567 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2568}
2569
2570/// Load (or add) an immediate into a register.
2571///
2572/// @param ImmValue The immediate to load.
2573/// @param DstReg The register that will hold the immediate.
2574/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2575/// for a simple initialization.
2576/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2577/// @param IsAddress True if the immediate represents an address. False if it
2578/// is an integer.
2579/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002580bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002581 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002582 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2583 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002584 MipsTargetStreamer &TOut = getTargetStreamer();
2585
Toma Tabacu00e98672015-05-01 12:19:27 +00002586 if (!Is32BitImm && !isGP64bit()) {
2587 Error(IDLoc, "instruction requires a 64-bit architecture");
2588 return true;
2589 }
2590
Daniel Sanders03f9c012015-07-14 12:24:22 +00002591 if (Is32BitImm) {
2592 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2593 // Sign extend up to 64-bit so that the predicates match the hardware
2594 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2595 // true.
2596 ImmValue = SignExtend64<32>(ImmValue);
2597 } else {
2598 Error(IDLoc, "instruction requires a 32-bit immediate");
2599 return true;
2600 }
2601 }
2602
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002603 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2604 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2605
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002606 bool UseSrcReg = false;
2607 if (SrcReg != Mips::NoRegister)
2608 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002609
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002610 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002611 if (UseSrcReg &&
2612 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002613 // At this point we need AT to perform the expansions and we exit if it is
2614 // not available.
2615 unsigned ATReg = getATReg(IDLoc);
2616 if (!ATReg)
2617 return true;
2618 TmpReg = ATReg;
2619 }
2620
Daniel Sanders03f9c012015-07-14 12:24:22 +00002621 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002622 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002623 SrcReg = ZeroReg;
2624
2625 // This doesn't quite follow the usual ABI expectations for N32 but matches
2626 // traditional assembler behaviour. N32 would normally use addiu for both
2627 // integers and addresses.
2628 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002629 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002630 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002631 }
2632
Daniel Sandersa736b372016-04-29 13:33:12 +00002633 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002634 return false;
2635 }
2636
2637 if (isUInt<16>(ImmValue)) {
2638 unsigned TmpReg = DstReg;
2639 if (SrcReg == DstReg) {
2640 TmpReg = getATReg(IDLoc);
2641 if (!TmpReg)
2642 return true;
2643 }
2644
Daniel Sandersa736b372016-04-29 13:33:12 +00002645 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002646 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002647 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002648 return false;
2649 }
2650
2651 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002652 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002653
Toma Tabacu79588102015-04-29 10:19:56 +00002654 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2655 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002656 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002657 // Traditional behaviour seems to special case this particular value. It's
2658 // not clear why other masks are handled differently.
2659 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002660 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2661 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002662 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002663 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002664 return false;
2665 }
2666
2667 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002668 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002669 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2670 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002671 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002672 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002673 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002674 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002675 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002676 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002677
Daniel Sandersa736b372016-04-29 13:33:12 +00002678 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002679 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002680 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002681 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002682 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002683 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002684 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002685
2686 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2687 if (Is32BitImm) {
2688 Error(IDLoc, "instruction requires a 32-bit immediate");
2689 return true;
2690 }
2691
2692 // Traditionally, these immediates are shifted as little as possible and as
2693 // such we align the most significant bit to bit 15 of our temporary.
2694 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2695 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2696 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2697 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002698 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2699 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002700
2701 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002702 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002703
2704 return false;
2705 }
2706
2707 warnIfNoMacro(IDLoc);
2708
2709 // The remaining case is packed with a sequence of dsll and ori with zeros
2710 // being omitted and any neighbouring dsll's being coalesced.
2711 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2712
2713 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2714 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002715 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002716 return false;
2717
2718 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2719 // skip it and defer the shift to the next chunk.
2720 unsigned ShiftCarriedForwards = 16;
2721 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2722 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2723
2724 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002725 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2726 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002727 ShiftCarriedForwards = 0;
2728 }
2729
2730 ShiftCarriedForwards += 16;
2731 }
2732 ShiftCarriedForwards -= 16;
2733
2734 // Finish any remaining shifts left by trailing zeros.
2735 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002736 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002737
2738 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002739 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002740
Matheus Almeida3813d572014-06-19 14:39:14 +00002741 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002742}
Jack Carter92995f12012-10-06 00:53:28 +00002743
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002744bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002745 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002746 const MCOperand &ImmOp = Inst.getOperand(1);
2747 assert(ImmOp.isImm() && "expected immediate operand kind");
2748 const MCOperand &DstRegOp = Inst.getOperand(0);
2749 assert(DstRegOp.isReg() && "expected register operand kind");
2750
2751 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002752 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002753 return true;
2754
2755 return false;
2756}
2757
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002758bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2759 const MCOperand &Offset,
2760 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002761 MCStreamer &Out,
2762 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002763 // la can't produce a usable address when addresses are 64-bit.
2764 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2765 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2766 // We currently can't do this because we depend on the equality
2767 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2768 Error(IDLoc, "la used to load 64-bit address");
2769 // Continue as if we had 'dla' instead.
2770 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002771 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002772 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002773
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002774 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002775 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002776 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002777 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002778 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002779
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002780 if (!Offset.isImm())
2781 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002782 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002783
Scott Egerton24557012016-01-21 15:11:01 +00002784 if (!ABI.ArePtrs64bit()) {
2785 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2786 Is32BitAddress = true;
2787 }
2788
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002789 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002790 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002791}
2792
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002793bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2794 unsigned DstReg, unsigned SrcReg,
2795 bool Is32BitSym, SMLoc IDLoc,
2796 MCStreamer &Out,
2797 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002798 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002799 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002800 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002801 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002802
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002803 if (inPicMode() && ABI.IsO32()) {
2804 MCValue Res;
2805 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2806 Error(IDLoc, "expected relocatable expression");
2807 return true;
2808 }
2809 if (Res.getSymB() != nullptr) {
2810 Error(IDLoc, "expected relocatable expression with only one symbol");
2811 return true;
2812 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002813
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002814 // The case where the result register is $25 is somewhat special. If the
2815 // symbol in the final relocation is external and not modified with a
2816 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2817 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002818 Res.getConstant() == 0 &&
2819 !(Res.getSymA()->getSymbol().isInSection() ||
2820 Res.getSymA()->getSymbol().isTemporary() ||
2821 (Res.getSymA()->getSymbol().isELF() &&
2822 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2823 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002824 const MCExpr *CallExpr =
2825 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2826 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2827 MCOperand::createExpr(CallExpr), IDLoc, STI);
2828 return false;
2829 }
2830
2831 // The remaining cases are:
2832 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2833 // >addiu $tmp, $tmp, %lo(offset)
2834 // >addiu $rd, $tmp, $rs
2835 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2836 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2837 // >addiu $rd, $tmp, $rs
2838 // The addiu's marked with a '>' may be omitted if they are redundant. If
2839 // this happens then the last instruction must use $rd as the result
2840 // register.
2841 const MipsMCExpr *GotExpr =
2842 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2843 const MCExpr *LoExpr = nullptr;
2844 if (Res.getSymA()->getSymbol().isInSection() ||
2845 Res.getSymA()->getSymbol().isTemporary())
2846 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2847 else if (Res.getConstant() != 0) {
2848 // External symbols fully resolve the symbol with just the %got(symbol)
2849 // but we must still account for any offset to the symbol for expressions
2850 // like symbol+8.
2851 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2852 }
2853
2854 unsigned TmpReg = DstReg;
2855 if (UseSrcReg &&
2856 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2857 SrcReg)) {
2858 // If $rs is the same as $rd, we need to use AT.
2859 // If it is not available we exit.
2860 unsigned ATReg = getATReg(IDLoc);
2861 if (!ATReg)
2862 return true;
2863 TmpReg = ATReg;
2864 }
2865
2866 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2867 MCOperand::createExpr(GotExpr), IDLoc, STI);
2868
2869 if (LoExpr)
2870 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2871 IDLoc, STI);
2872
2873 if (UseSrcReg)
2874 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2875
2876 return false;
2877 }
2878
Simon Dardisda96c432017-06-30 15:44:27 +00002879 if (inPicMode() && ABI.ArePtrs64bit()) {
2880 MCValue Res;
2881 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2882 Error(IDLoc, "expected relocatable expression");
2883 return true;
2884 }
2885 if (Res.getSymB() != nullptr) {
2886 Error(IDLoc, "expected relocatable expression with only one symbol");
2887 return true;
2888 }
2889
2890 // The case where the result register is $25 is somewhat special. If the
2891 // symbol in the final relocation is external and not modified with a
2892 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2893 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2894 Res.getConstant() == 0 &&
2895 !(Res.getSymA()->getSymbol().isInSection() ||
2896 Res.getSymA()->getSymbol().isTemporary() ||
2897 (Res.getSymA()->getSymbol().isELF() &&
2898 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2899 ELF::STB_LOCAL))) {
2900 const MCExpr *CallExpr =
2901 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2902 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2903 MCOperand::createExpr(CallExpr), IDLoc, STI);
2904 return false;
2905 }
2906
2907 // The remaining cases are:
2908 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2909 // >daddiu $tmp, $tmp, offset
2910 // >daddu $rd, $tmp, $rs
2911 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2912 // this happens then the last instruction must use $rd as the result
2913 // register.
2914 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2915 Res.getSymA(),
2916 getContext());
2917 const MCExpr *LoExpr = nullptr;
2918 if (Res.getConstant() != 0) {
2919 // Symbols fully resolve with just the %got_disp(symbol) but we
2920 // must still account for any offset to the symbol for
2921 // expressions like symbol+8.
2922 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2923
2924 // FIXME: Offsets greater than 16 bits are not yet implemented.
2925 // FIXME: The correct range is a 32-bit sign-extended number.
2926 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2927 Error(IDLoc, "macro instruction uses large offset, which is not "
2928 "currently supported");
2929 return true;
2930 }
2931 }
2932
2933 unsigned TmpReg = DstReg;
2934 if (UseSrcReg &&
2935 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2936 SrcReg)) {
2937 // If $rs is the same as $rd, we need to use AT.
2938 // If it is not available we exit.
2939 unsigned ATReg = getATReg(IDLoc);
2940 if (!ATReg)
2941 return true;
2942 TmpReg = ATReg;
2943 }
2944
2945 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
2946 MCOperand::createExpr(GotExpr), IDLoc, STI);
2947
2948 if (LoExpr)
2949 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2950 IDLoc, STI);
2951
2952 if (UseSrcReg)
2953 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2954
2955 return false;
2956 }
2957
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002958 const MipsMCExpr *HiExpr =
2959 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2960 const MipsMCExpr *LoExpr =
2961 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002962
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002963 // This is the 64-bit symbol address expansion.
2964 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00002965 // We need AT for the 64-bit expansion in the cases where the optional
2966 // source register is the destination register and for the superscalar
2967 // scheduled form.
2968 //
2969 // If it is not available we exit if the destination is the same as the
2970 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002971
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002972 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002973 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002974 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002975 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002976
Simon Dardis3aa8a902017-02-06 12:43:46 +00002977 bool RdRegIsRsReg =
2978 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
2979
2980 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
2981 unsigned ATReg = getATReg(IDLoc);
2982
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002983 // If $rs is the same as $rd:
2984 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2985 // daddiu $at, $at, %higher(sym)
2986 // dsll $at, $at, 16
2987 // daddiu $at, $at, %hi(sym)
2988 // dsll $at, $at, 16
2989 // daddiu $at, $at, %lo(sym)
2990 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002991 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2992 STI);
2993 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2994 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2995 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2996 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2997 IDLoc, STI);
2998 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2999 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3000 IDLoc, STI);
3001 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003002
3003 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00003004 } else if (canUseATReg() && !RdRegIsRsReg) {
3005 unsigned ATReg = getATReg(IDLoc);
3006
3007 // If the $rs is different from $rd or if $rs isn't specified and we
3008 // have $at available:
3009 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3010 // lui $at, %hi(sym)
3011 // daddiu $rd, $rd, %higher(sym)
3012 // daddiu $at, $at, %lo(sym)
3013 // dsll32 $rd, $rd, 0
3014 // daddu $rd, $rd, $at
3015 // (daddu $rd, $rd, $rs)
3016 //
3017 // Which is preferred for superscalar issue.
3018 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3019 STI);
3020 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3021 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3022 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3023 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3024 IDLoc, STI);
3025 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3026 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3027 if (UseSrcReg)
3028 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3029
3030 return false;
3031 } else if (!canUseATReg() && !RdRegIsRsReg) {
3032 // Otherwise, synthesize the address in the destination register
3033 // serially:
3034 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3035 // daddiu $rd, $rd, %higher(sym)
3036 // dsll $rd, $rd, 16
3037 // daddiu $rd, $rd, %hi(sym)
3038 // dsll $rd, $rd, 16
3039 // daddiu $rd, $rd, %lo(sym)
3040 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3041 STI);
3042 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3043 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3044 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3045 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3046 MCOperand::createExpr(HiExpr), IDLoc, STI);
3047 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3048 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3049 MCOperand::createExpr(LoExpr), IDLoc, STI);
3050 if (UseSrcReg)
3051 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3052
3053 return false;
3054 } else {
3055 // We have a case where SrcReg == DstReg and we don't have $at
3056 // available. We can't expand this case, so error out appropriately.
3057 assert(SrcReg == DstReg && !canUseATReg() &&
3058 "Could have expanded dla but didn't?");
3059 reportParseError(IDLoc,
3060 "pseudo-instruction requires $at, which is not available");
3061 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003062 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003063 }
3064
3065 // And now, the 32-bit symbol address expansion:
3066 // If $rs is the same as $rd:
3067 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3068 // ori $at, $at, %lo(sym)
3069 // addu $rd, $at, $rd
3070 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3071 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3072 // ori $rd, $rd, %lo(sym)
3073 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003074 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003075 if (UseSrcReg &&
3076 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003077 // If $rs is the same as $rd, we need to use AT.
3078 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003079 unsigned ATReg = getATReg(IDLoc);
3080 if (!ATReg)
3081 return true;
3082 TmpReg = ATReg;
3083 }
3084
Daniel Sandersa736b372016-04-29 13:33:12 +00003085 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3086 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3087 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003088
Toma Tabacufb9d1252015-06-22 12:08:39 +00003089 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003090 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003091 else
Scott Egerton24557012016-01-21 15:11:01 +00003092 assert(
3093 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003094
Toma Tabacu674825c2015-06-16 12:16:24 +00003095 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003096}
3097
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003098// Each double-precision register DO-D15 overlaps with two of the single
3099// precision registers F0-F31. As an example, all of the following hold true:
3100// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3101static unsigned nextReg(unsigned Reg) {
3102 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3103 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3104 switch (Reg) {
3105 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3106 case Mips::ZERO: return Mips::AT;
3107 case Mips::AT: return Mips::V0;
3108 case Mips::V0: return Mips::V1;
3109 case Mips::V1: return Mips::A0;
3110 case Mips::A0: return Mips::A1;
3111 case Mips::A1: return Mips::A2;
3112 case Mips::A2: return Mips::A3;
3113 case Mips::A3: return Mips::T0;
3114 case Mips::T0: return Mips::T1;
3115 case Mips::T1: return Mips::T2;
3116 case Mips::T2: return Mips::T3;
3117 case Mips::T3: return Mips::T4;
3118 case Mips::T4: return Mips::T5;
3119 case Mips::T5: return Mips::T6;
3120 case Mips::T6: return Mips::T7;
3121 case Mips::T7: return Mips::S0;
3122 case Mips::S0: return Mips::S1;
3123 case Mips::S1: return Mips::S2;
3124 case Mips::S2: return Mips::S3;
3125 case Mips::S3: return Mips::S4;
3126 case Mips::S4: return Mips::S5;
3127 case Mips::S5: return Mips::S6;
3128 case Mips::S6: return Mips::S7;
3129 case Mips::S7: return Mips::T8;
3130 case Mips::T8: return Mips::T9;
3131 case Mips::T9: return Mips::K0;
3132 case Mips::K0: return Mips::K1;
3133 case Mips::K1: return Mips::GP;
3134 case Mips::GP: return Mips::SP;
3135 case Mips::SP: return Mips::FP;
3136 case Mips::FP: return Mips::RA;
3137 case Mips::RA: return Mips::ZERO;
3138 case Mips::D0: return Mips::F1;
3139 case Mips::D1: return Mips::F3;
3140 case Mips::D2: return Mips::F5;
3141 case Mips::D3: return Mips::F7;
3142 case Mips::D4: return Mips::F9;
3143 case Mips::D5: return Mips::F11;
3144 case Mips::D6: return Mips::F13;
3145 case Mips::D7: return Mips::F15;
3146 case Mips::D8: return Mips::F17;
3147 case Mips::D9: return Mips::F19;
3148 case Mips::D10: return Mips::F21;
3149 case Mips::D11: return Mips::F23;
3150 case Mips::D12: return Mips::F25;
3151 case Mips::D13: return Mips::F27;
3152 case Mips::D14: return Mips::F29;
3153 case Mips::D15: return Mips::F31;
3154 }
3155}
3156
3157// FIXME: This method is too general. In principle we should compute the number
3158// of instructions required to synthesize the immediate inline compared to
3159// synthesizing the address inline and relying on non .text sections.
3160// For static O32 and N32 this may yield a small benefit, for static N64 this is
3161// likely to yield a much larger benefit as we have to synthesize a 64bit
3162// address to load a 64 bit value.
3163bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3164 MCSymbol *Sym) {
3165 unsigned ATReg = getATReg(IDLoc);
3166 if (!ATReg)
3167 return true;
3168
3169 if(IsPicEnabled) {
3170 const MCExpr *GotSym =
3171 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3172 const MipsMCExpr *GotExpr =
3173 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3174
3175 if(isABI_O32() || isABI_N32()) {
3176 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3177 IDLoc, STI);
3178 } else { //isABI_N64()
3179 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3180 IDLoc, STI);
3181 }
3182 } else { //!IsPicEnabled
3183 const MCExpr *HiSym =
3184 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3185 const MipsMCExpr *HiExpr =
3186 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3187
3188 // FIXME: This is technically correct but gives a different result to gas,
3189 // but gas is incomplete there (it has a fixme noting it doesn't work with
3190 // 64-bit addresses).
3191 // FIXME: With -msym32 option, the address expansion for N64 should probably
3192 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3193 // symbol's value is considered sign extended.
3194 if(isABI_O32() || isABI_N32()) {
3195 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3196 } else { //isABI_N64()
3197 const MCExpr *HighestSym =
3198 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3199 const MipsMCExpr *HighestExpr =
3200 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3201 const MCExpr *HigherSym =
3202 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3203 const MipsMCExpr *HigherExpr =
3204 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3205
3206 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3207 STI);
3208 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3209 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3210 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3211 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3212 IDLoc, STI);
3213 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3214 }
3215 }
3216 return false;
3217}
3218
3219bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3220 bool Is64FPU, SMLoc IDLoc,
3221 MCStreamer &Out,
3222 const MCSubtargetInfo *STI) {
3223 MipsTargetStreamer &TOut = getTargetStreamer();
3224 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3225 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3226 "Invalid instruction operand.");
3227
3228 unsigned FirstReg = Inst.getOperand(0).getReg();
3229 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3230
3231 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3232 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3233 // exponent field), convert it to double (e.g. 1 to 1.0)
3234 if ((HiImmOp64 & 0x7ff00000) == 0) {
3235 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3236 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3237 }
3238
3239 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3240 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3241
3242 if (IsSingle) {
3243 // Conversion of a double in an uint64_t to a float in a uint32_t,
3244 // retaining the bit pattern of a float.
3245 uint32_t ImmOp32;
3246 double doubleImm = BitsToDouble(ImmOp64);
3247 float tmp_float = static_cast<float>(doubleImm);
3248 ImmOp32 = FloatToBits(tmp_float);
3249
3250 if (IsGPR) {
3251 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3252 Out, STI))
3253 return true;
3254 return false;
3255 } else {
3256 unsigned ATReg = getATReg(IDLoc);
3257 if (!ATReg)
3258 return true;
3259 if (LoImmOp64 == 0) {
3260 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3261 Out, STI))
3262 return true;
3263 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3264 return false;
3265 }
3266
3267 MCSection *CS = getStreamer().getCurrentSectionOnly();
3268 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3269 // where appropriate.
3270 MCSection *ReadOnlySection = getContext().getELFSection(
3271 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3272
3273 MCSymbol *Sym = getContext().createTempSymbol();
3274 const MCExpr *LoSym =
3275 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3276 const MipsMCExpr *LoExpr =
3277 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3278
3279 getStreamer().SwitchSection(ReadOnlySection);
3280 getStreamer().EmitLabel(Sym, IDLoc);
3281 getStreamer().EmitIntValue(ImmOp32, 4);
3282 getStreamer().SwitchSection(CS);
3283
3284 if(emitPartialAddress(TOut, IDLoc, Sym))
3285 return true;
3286 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3287 MCOperand::createExpr(LoExpr), IDLoc, STI);
3288 }
3289 return false;
3290 }
3291
3292 // if(!IsSingle)
3293 unsigned ATReg = getATReg(IDLoc);
3294 if (!ATReg)
3295 return true;
3296
3297 if (IsGPR) {
3298 if (LoImmOp64 == 0) {
3299 if(isABI_N32() || isABI_N64()) {
3300 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3301 IDLoc, Out, STI))
3302 return true;
3303 return false;
3304 } else {
3305 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3306 IDLoc, Out, STI))
3307 return true;
3308
3309 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3310 IDLoc, Out, STI))
3311 return true;
3312 return false;
3313 }
3314 }
3315
3316 MCSection *CS = getStreamer().getCurrentSectionOnly();
3317 MCSection *ReadOnlySection = getContext().getELFSection(
3318 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3319
3320 MCSymbol *Sym = getContext().createTempSymbol();
3321 const MCExpr *LoSym =
3322 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3323 const MipsMCExpr *LoExpr =
3324 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3325
3326 getStreamer().SwitchSection(ReadOnlySection);
3327 getStreamer().EmitLabel(Sym, IDLoc);
3328 getStreamer().EmitIntValue(HiImmOp64, 4);
3329 getStreamer().EmitIntValue(LoImmOp64, 4);
3330 getStreamer().SwitchSection(CS);
3331
3332 if(emitPartialAddress(TOut, IDLoc, Sym))
3333 return true;
3334 if(isABI_N64())
3335 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3336 MCOperand::createExpr(LoExpr), IDLoc, STI);
3337 else
3338 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3339 MCOperand::createExpr(LoExpr), IDLoc, STI);
3340
3341 if(isABI_N32() || isABI_N64())
3342 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3343 else {
3344 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3345 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3346 }
3347 return false;
3348 } else { // if(!IsGPR && !IsSingle)
3349 if ((LoImmOp64 == 0) &&
3350 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3351 // FIXME: In the case where the constant is zero, we can load the
3352 // register directly from the zero register.
3353 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3354 Out, STI))
3355 return true;
3356 if (isABI_N32() || isABI_N64())
3357 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3358 else if (hasMips32r2()) {
3359 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3360 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3361 } else {
3362 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3363 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3364 }
3365 return false;
3366 }
3367
3368 MCSection *CS = getStreamer().getCurrentSectionOnly();
3369 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3370 // where appropriate.
3371 MCSection *ReadOnlySection = getContext().getELFSection(
3372 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3373
3374 MCSymbol *Sym = getContext().createTempSymbol();
3375 const MCExpr *LoSym =
3376 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3377 const MipsMCExpr *LoExpr =
3378 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3379
3380 getStreamer().SwitchSection(ReadOnlySection);
3381 getStreamer().EmitLabel(Sym, IDLoc);
3382 getStreamer().EmitIntValue(HiImmOp64, 4);
3383 getStreamer().EmitIntValue(LoImmOp64, 4);
3384 getStreamer().SwitchSection(CS);
3385
3386 if(emitPartialAddress(TOut, IDLoc, Sym))
3387 return true;
3388 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3389 MCOperand::createExpr(LoExpr), IDLoc, STI);
3390 }
3391 return false;
3392}
3393
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003394bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3395 MCStreamer &Out,
3396 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003397 MipsTargetStreamer &TOut = getTargetStreamer();
3398
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003399 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3400 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003401
3402 MCOperand Offset = Inst.getOperand(0);
3403 if (Offset.isExpr()) {
3404 Inst.clear();
3405 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003406 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3407 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3408 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003409 } else {
3410 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003411 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003412 // If offset fits into 11 bits then this instruction becomes microMIPS
3413 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003414 if (inMicroMipsMode())
3415 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003416 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003417 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003418 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003419 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003420 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003421 Inst.clear();
3422 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003423 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3424 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3425 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003426 }
3427 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003428 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003429
Zoran Jovanovicada70912015-09-07 11:56:37 +00003430 // If .set reorder is active and branch instruction has a delay slot,
3431 // emit a NOP after it.
3432 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3433 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003434 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003435
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003436 return false;
3437}
3438
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003439bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3440 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003441 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003442 const MCOperand &DstRegOp = Inst.getOperand(0);
3443 assert(DstRegOp.isReg() && "expected register operand kind");
3444
3445 const MCOperand &ImmOp = Inst.getOperand(1);
3446 assert(ImmOp.isImm() && "expected immediate operand kind");
3447
3448 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003449 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3450 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003451
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003452 bool IsLikely = false;
3453
Toma Tabacue1e460d2015-06-11 10:36:10 +00003454 unsigned OpCode = 0;
3455 switch(Inst.getOpcode()) {
3456 case Mips::BneImm:
3457 OpCode = Mips::BNE;
3458 break;
3459 case Mips::BeqImm:
3460 OpCode = Mips::BEQ;
3461 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003462 case Mips::BEQLImmMacro:
3463 OpCode = Mips::BEQL;
3464 IsLikely = true;
3465 break;
3466 case Mips::BNELImmMacro:
3467 OpCode = Mips::BNEL;
3468 IsLikely = true;
3469 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003470 default:
3471 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3472 break;
3473 }
3474
3475 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003476 if (ImmValue == 0) {
3477 if (IsLikely) {
3478 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3479 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3480 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3481 } else
3482 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3483 STI);
3484 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003485 warnIfNoMacro(IDLoc);
3486
3487 unsigned ATReg = getATReg(IDLoc);
3488 if (!ATReg)
3489 return true;
3490
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003491 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003492 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003493 return true;
3494
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003495 if (IsLikely) {
3496 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3497 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3498 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3499 } else
3500 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003501 }
3502 return false;
3503}
3504
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003505void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00003506 const MCSubtargetInfo *STI, bool IsLoad,
3507 bool IsImmOpnd) {
3508 if (IsLoad) {
3509 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3510 return;
Scott Egertond65377d2016-03-17 10:37:51 +00003511 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003512 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3513}
3514
3515void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3516 const MCSubtargetInfo *STI, bool IsImmOpnd) {
3517 MipsTargetStreamer &TOut = getTargetStreamer();
3518
3519 unsigned DstReg = Inst.getOperand(0).getReg();
3520 unsigned BaseReg = Inst.getOperand(1).getReg();
3521
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003522 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003523 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3524 unsigned DstRegClassID =
3525 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3526 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3527 (DstRegClassID == Mips::GPR64RegClassID);
3528
3529 if (IsImmOpnd) {
3530 // Try to use DstReg as the temporary.
3531 if (IsGPR && (BaseReg != DstReg)) {
3532 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3533 Inst.getOperand(2).getImm(), DstReg, IDLoc,
3534 STI);
3535 return;
3536 }
3537
Matheus Almeida7de68e72014-06-18 14:46:05 +00003538 // At this point we need AT to perform the expansions and we exit if it is
3539 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00003540 unsigned ATReg = getATReg(IDLoc);
3541 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00003542 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003543
3544 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3545 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
3546 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00003547 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00003548
Daniel Sandersfba875f2016-04-29 13:43:45 +00003549 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003550 MCOperand LoOperand = MCOperand::createExpr(
3551 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3552 MCOperand HiOperand = MCOperand::createExpr(
3553 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003554
3555 // Try to use DstReg as the temporary.
3556 if (IsGPR && (BaseReg != DstReg)) {
3557 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3558 LoOperand, DstReg, IDLoc, STI);
3559 return;
3560 }
3561
3562 // At this point we need AT to perform the expansions and we exit if it is
3563 // not available.
3564 unsigned ATReg = getATReg(IDLoc);
3565 if (!ATReg)
3566 return;
3567
3568 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3569 LoOperand, ATReg, IDLoc, STI);
3570}
3571
3572void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3573 const MCSubtargetInfo *STI,
3574 bool IsImmOpnd) {
3575 MipsTargetStreamer &TOut = getTargetStreamer();
3576
3577 unsigned SrcReg = Inst.getOperand(0).getReg();
3578 unsigned BaseReg = Inst.getOperand(1).getReg();
3579
Daniel Sanders241c6792016-05-12 14:01:50 +00003580 if (IsImmOpnd) {
3581 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
3582 Inst.getOperand(2).getImm(),
3583 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3584 return;
3585 }
3586
Daniel Sandersfba875f2016-04-29 13:43:45 +00003587 unsigned ATReg = getATReg(IDLoc);
3588 if (!ATReg)
3589 return;
3590
Daniel Sandersfba875f2016-04-29 13:43:45 +00003591 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003592 MCOperand LoOperand = MCOperand::createExpr(
3593 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3594 MCOperand HiOperand = MCOperand::createExpr(
3595 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003596 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3597 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003598}
3599
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003600bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3601 MCStreamer &Out,
3602 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003603 unsigned OpNum = Inst.getNumOperands();
3604 unsigned Opcode = Inst.getOpcode();
3605 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3606
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003607 assert(Inst.getOperand(OpNum - 1).isImm() &&
3608 Inst.getOperand(OpNum - 2).isReg() &&
3609 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003610
3611 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3612 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003613 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3614 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3615 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3616 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003617 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003618 if (inMicroMipsMode() && hasMips32r6())
3619 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3620 else
3621 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3622 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003623
3624 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003625 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003626 return false;
3627}
3628
Toma Tabacu1a108322015-06-17 13:20:24 +00003629bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003630 MCStreamer &Out,
3631 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003632 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003633 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003634 unsigned PseudoOpcode = Inst.getOpcode();
3635 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003636 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003637 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3638
3639 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003640 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003641
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003642 unsigned TrgReg;
3643 if (TrgOp.isReg())
3644 TrgReg = TrgOp.getReg();
3645 else if (TrgOp.isImm()) {
3646 warnIfNoMacro(IDLoc);
3647 EmittedNoMacroWarning = true;
3648
3649 TrgReg = getATReg(IDLoc);
3650 if (!TrgReg)
3651 return true;
3652
3653 switch(PseudoOpcode) {
3654 default:
3655 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3656 case Mips::BLTImmMacro:
3657 PseudoOpcode = Mips::BLT;
3658 break;
3659 case Mips::BLEImmMacro:
3660 PseudoOpcode = Mips::BLE;
3661 break;
3662 case Mips::BGEImmMacro:
3663 PseudoOpcode = Mips::BGE;
3664 break;
3665 case Mips::BGTImmMacro:
3666 PseudoOpcode = Mips::BGT;
3667 break;
3668 case Mips::BLTUImmMacro:
3669 PseudoOpcode = Mips::BLTU;
3670 break;
3671 case Mips::BLEUImmMacro:
3672 PseudoOpcode = Mips::BLEU;
3673 break;
3674 case Mips::BGEUImmMacro:
3675 PseudoOpcode = Mips::BGEU;
3676 break;
3677 case Mips::BGTUImmMacro:
3678 PseudoOpcode = Mips::BGTU;
3679 break;
3680 case Mips::BLTLImmMacro:
3681 PseudoOpcode = Mips::BLTL;
3682 break;
3683 case Mips::BLELImmMacro:
3684 PseudoOpcode = Mips::BLEL;
3685 break;
3686 case Mips::BGELImmMacro:
3687 PseudoOpcode = Mips::BGEL;
3688 break;
3689 case Mips::BGTLImmMacro:
3690 PseudoOpcode = Mips::BGTL;
3691 break;
3692 case Mips::BLTULImmMacro:
3693 PseudoOpcode = Mips::BLTUL;
3694 break;
3695 case Mips::BLEULImmMacro:
3696 PseudoOpcode = Mips::BLEUL;
3697 break;
3698 case Mips::BGEULImmMacro:
3699 PseudoOpcode = Mips::BGEUL;
3700 break;
3701 case Mips::BGTULImmMacro:
3702 PseudoOpcode = Mips::BGTUL;
3703 break;
3704 }
3705
3706 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003707 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003708 return true;
3709 }
3710
Toma Tabacu1a108322015-06-17 13:20:24 +00003711 switch (PseudoOpcode) {
3712 case Mips::BLT:
3713 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003714 case Mips::BLTL:
3715 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003716 AcceptsEquality = false;
3717 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003718 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3719 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003720 ZeroSrcOpcode = Mips::BGTZ;
3721 ZeroTrgOpcode = Mips::BLTZ;
3722 break;
3723 case Mips::BLE:
3724 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003725 case Mips::BLEL:
3726 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003727 AcceptsEquality = true;
3728 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003729 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3730 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003731 ZeroSrcOpcode = Mips::BGEZ;
3732 ZeroTrgOpcode = Mips::BLEZ;
3733 break;
3734 case Mips::BGE:
3735 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003736 case Mips::BGEL:
3737 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003738 AcceptsEquality = true;
3739 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003740 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3741 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003742 ZeroSrcOpcode = Mips::BLEZ;
3743 ZeroTrgOpcode = Mips::BGEZ;
3744 break;
3745 case Mips::BGT:
3746 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003747 case Mips::BGTL:
3748 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003749 AcceptsEquality = false;
3750 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003751 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3752 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003753 ZeroSrcOpcode = Mips::BLTZ;
3754 ZeroTrgOpcode = Mips::BGTZ;
3755 break;
3756 default:
3757 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3758 }
3759
Toma Tabacu1a108322015-06-17 13:20:24 +00003760 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3761 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3762 if (IsSrcRegZero && IsTrgRegZero) {
3763 // FIXME: All of these Opcode-specific if's are needed for compatibility
3764 // with GAS' behaviour. However, they may not generate the most efficient
3765 // code in some circumstances.
3766 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003767 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3768 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003769 return false;
3770 }
3771 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003772 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3773 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003774 Warning(IDLoc, "branch is always taken");
3775 return false;
3776 }
3777 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003778 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3779 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003780 Warning(IDLoc, "branch is always taken");
3781 return false;
3782 }
3783 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003784 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3785 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003786 return false;
3787 }
3788 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003789 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3790 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003791 return false;
3792 }
3793 if (AcceptsEquality) {
3794 // If both registers are $0 and the pseudo-branch accepts equality, it
3795 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003796 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3797 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003798 Warning(IDLoc, "branch is always taken");
3799 return false;
3800 }
3801 // If both registers are $0 and the pseudo-branch does not accept
3802 // equality, it will never be taken, so we don't have to emit anything.
3803 return false;
3804 }
3805 if (IsSrcRegZero || IsTrgRegZero) {
3806 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3807 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3808 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3809 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3810 // the pseudo-branch will never be taken, so we don't emit anything.
3811 // This only applies to unsigned pseudo-branches.
3812 return false;
3813 }
3814 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3815 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3816 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3817 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3818 // the pseudo-branch will always be taken, so we emit an unconditional
3819 // branch.
3820 // This only applies to unsigned pseudo-branches.
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 (IsUnsigned) {
3827 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3828 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3829 // the pseudo-branch will be taken only when the non-zero register is
3830 // different from 0, so we emit a BNEZ.
3831 //
3832 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3833 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3834 // the pseudo-branch will be taken only when the non-zero register is
3835 // equal to 0, so we emit a BEQZ.
3836 //
3837 // Because only BLEU and BGEU branch on equality, we can use the
3838 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003839 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3840 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3841 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003842 return false;
3843 }
3844 // If we have a signed pseudo-branch and one of the registers is $0,
3845 // we can use an appropriate compare-to-zero branch. We select which one
3846 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003847 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3848 IsSrcRegZero ? TrgReg : SrcReg,
3849 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003850 return false;
3851 }
3852
3853 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3854 // expansions. If it is not available, we return.
3855 unsigned ATRegNum = getATReg(IDLoc);
3856 if (!ATRegNum)
3857 return true;
3858
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003859 if (!EmittedNoMacroWarning)
3860 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003861
3862 // SLT fits well with 2 of our 4 pseudo-branches:
3863 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3864 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3865 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3866 // This is accomplished by using a BNEZ with the result of the SLT.
3867 //
3868 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3869 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3870 // Because only BGE and BLE branch on equality, we can use the
3871 // AcceptsEquality variable to decide when to emit the BEQZ.
3872 // Note that the order of the SLT arguments doesn't change between
3873 // opposites.
3874 //
3875 // The same applies to the unsigned variants, except that SLTu is used
3876 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003877 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3878 ReverseOrderSLT ? TrgReg : SrcReg,
3879 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003880
Daniel Sandersa736b372016-04-29 13:33:12 +00003881 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3882 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3883 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3884 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003885 return false;
3886}
3887
Simon Dardis509da1a2017-02-13 16:06:48 +00003888// Expand a integer division macro.
3889//
3890// Notably we don't have to emit a warning when encountering $rt as the $zero
3891// register, or 0 as an immediate. processInstruction() has already done that.
3892//
3893// The destination register can only be $zero when expanding (S)DivIMacro or
3894// D(S)DivMacro.
3895
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003896bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3897 const MCSubtargetInfo *STI, const bool IsMips64,
3898 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003899 MipsTargetStreamer &TOut = getTargetStreamer();
3900
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003901 warnIfNoMacro(IDLoc);
3902
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003903 const MCOperand &RdRegOp = Inst.getOperand(0);
3904 assert(RdRegOp.isReg() && "expected register operand kind");
3905 unsigned RdReg = RdRegOp.getReg();
3906
3907 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003908 assert(RsRegOp.isReg() && "expected register operand kind");
3909 unsigned RsReg = RsRegOp.getReg();
3910
Simon Dardis12850ee2017-01-31 10:49:24 +00003911 unsigned RtReg;
3912 int64_t ImmValue;
3913
3914 const MCOperand &RtOp = Inst.getOperand(2);
3915 assert((RtOp.isReg() || RtOp.isImm()) &&
3916 "expected register or immediate operand kind");
3917 if (RtOp.isReg())
3918 RtReg = RtOp.getReg();
3919 else
3920 ImmValue = RtOp.getImm();
3921
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003922 unsigned DivOp;
3923 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003924 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003925
3926 if (IsMips64) {
3927 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3928 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003929 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003930 } else {
3931 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3932 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003933 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003934 }
3935
3936 bool UseTraps = useTraps();
3937
Simon Dardis12850ee2017-01-31 10:49:24 +00003938 if (RtOp.isImm()) {
3939 unsigned ATReg = getATReg(IDLoc);
3940 if (!ATReg)
3941 return true;
3942
3943 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003944 if (UseTraps)
3945 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3946 else
3947 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3948 return false;
3949 }
3950
3951 if (ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003952 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003953 return false;
3954 } else if (Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003955 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003956 return false;
3957 } else {
3958 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
3959 false, Inst.getLoc(), Out, STI))
3960 return true;
3961 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
3962 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
3963 return false;
3964 }
3965 return true;
3966 }
3967
Simon Dardis509da1a2017-02-13 16:06:48 +00003968 // If the macro expansion of (d)div(u) would always trap or break, insert
3969 // the trap/break and exit. This gives a different result to GAS. GAS has
3970 // an inconsistency/missed optimization in that not all cases are handled
3971 // equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003972 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003973 if (UseTraps) {
3974 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003975 return false;
3976 }
Simon Dardis509da1a2017-02-13 16:06:48 +00003977 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3978 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003979 }
3980
Simon Dardis509da1a2017-02-13 16:06:48 +00003981 // Temporary label for first branch traget
3982 MCContext &Context = TOut.getStreamer().getContext();
3983 MCSymbol *BrTarget;
3984 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003985
3986 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003987 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003988 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003989 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00003990 BrTarget = Context.createTempSymbol();
3991 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
3992 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003993 }
3994
Daniel Sandersa736b372016-04-29 13:33:12 +00003995 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003996
3997 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003998 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003999
4000 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004001 if (!UseTraps)
4002 TOut.getStreamer().EmitLabel(BrTarget);
4003
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004004 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004005 return false;
4006 }
4007
4008 unsigned ATReg = getATReg(IDLoc);
4009 if (!ATReg)
4010 return true;
4011
Simon Dardis509da1a2017-02-13 16:06:48 +00004012 if (!UseTraps)
4013 TOut.getStreamer().EmitLabel(BrTarget);
4014
Daniel Sandersa736b372016-04-29 13:33:12 +00004015 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004016
4017 // Temporary label for the second branch target.
4018 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4019 MCOperand LabelOpEnd =
4020 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4021
4022 // Branch to the mflo instruction.
4023 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4024
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004025 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004026 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
4027 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004028 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004029 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004030 }
4031
4032 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004033 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004034 else {
4035 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004036 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004037 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
4038 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004039 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004040
4041 TOut.getStreamer().EmitLabel(BrTargetEnd);
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004042 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004043 return false;
4044}
4045
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004046bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004047 SMLoc IDLoc, MCStreamer &Out,
4048 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004049 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004050
4051 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4052 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4053 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4054
4055 unsigned FirstReg = Inst.getOperand(0).getReg();
4056 unsigned SecondReg = Inst.getOperand(1).getReg();
4057 unsigned ThirdReg = Inst.getOperand(2).getReg();
4058
4059 if (hasMips1() && !hasMips2()) {
4060 unsigned ATReg = getATReg(IDLoc);
4061 if (!ATReg)
4062 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004063 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4064 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4065 TOut.emitNop(IDLoc, STI);
4066 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4067 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4068 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4069 TOut.emitNop(IDLoc, STI);
4070 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4071 : Mips::CVT_W_S,
4072 FirstReg, SecondReg, IDLoc, STI);
4073 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4074 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004075 return false;
4076 }
4077
Daniel Sandersa736b372016-04-29 13:33:12 +00004078 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4079 : Mips::TRUNC_W_S,
4080 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004081
4082 return false;
4083}
4084
Daniel Sanders6394ee52015-10-15 14:52:58 +00004085bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004086 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004087 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004088 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004089 }
4090
Toma Tabacud88d79c2015-06-23 14:39:42 +00004091 const MCOperand &DstRegOp = Inst.getOperand(0);
4092 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004093 const MCOperand &SrcRegOp = Inst.getOperand(1);
4094 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004095 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4096 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4097
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004098 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004099 unsigned DstReg = DstRegOp.getReg();
4100 unsigned SrcReg = SrcRegOp.getReg();
4101 int64_t OffsetValue = OffsetImmOp.getImm();
4102
4103 // NOTE: We always need AT for ULHU, as it is always used as the source
4104 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004105 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004106 unsigned ATReg = getATReg(IDLoc);
4107 if (!ATReg)
4108 return true;
4109
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004110 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4111 if (IsLargeOffset) {
4112 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4113 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004114 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004115 }
4116
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004117 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4118 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4119 if (isLittle())
4120 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004121
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004122 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4123 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004124
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004125 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4126 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004127
Daniel Sandersa736b372016-04-29 13:33:12 +00004128 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004129 FirstOffset, IDLoc, STI);
4130 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004131 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004132 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004133
4134 return false;
4135}
4136
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004137bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004138 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004139 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004140 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004141 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004142
4143 const MCOperand &DstRegOp = Inst.getOperand(0);
4144 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004145 const MCOperand &SrcRegOp = Inst.getOperand(1);
4146 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004147 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4148 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4149
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004150 MipsTargetStreamer &TOut = getTargetStreamer();
4151 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004152 unsigned SrcReg = SrcRegOp.getReg();
4153 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004154
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004155 warnIfNoMacro(IDLoc);
4156 unsigned ATReg = getATReg(IDLoc);
4157 if (!ATReg)
4158 return true;
4159
4160 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4161 if (IsLargeOffset) {
4162 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4163 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004164 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004165 }
4166
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004167 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4168 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4169 if (isLittle())
4170 std::swap(FirstOffset, SecondOffset);
4171
4172 if (IsLargeOffset) {
4173 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4174 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4175 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4176 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4177 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4178 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004179 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004180 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4181 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4182 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004183 }
4184
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004185 return false;
4186}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004187
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004188bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4189 const MCSubtargetInfo *STI) {
4190 if (hasMips32r6() || hasMips64r6()) {
4191 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4192 }
4193
4194 const MCOperand &DstRegOp = Inst.getOperand(0);
4195 assert(DstRegOp.isReg() && "expected register operand kind");
4196 const MCOperand &SrcRegOp = Inst.getOperand(1);
4197 assert(SrcRegOp.isReg() && "expected register operand kind");
4198 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4199 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4200
4201 MipsTargetStreamer &TOut = getTargetStreamer();
4202 unsigned DstReg = DstRegOp.getReg();
4203 unsigned SrcReg = SrcRegOp.getReg();
4204 int64_t OffsetValue = OffsetImmOp.getImm();
4205
4206 // Compute left/right load/store offsets.
4207 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4208 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4209 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4210 if (isLittle())
4211 std::swap(LxlOffset, LxrOffset);
4212
4213 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4214 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4215 unsigned TmpReg = SrcReg;
4216 if (IsLargeOffset || DoMove) {
4217 warnIfNoMacro(IDLoc);
4218 TmpReg = getATReg(IDLoc);
4219 if (!TmpReg)
4220 return true;
4221 }
4222
4223 if (IsLargeOffset) {
4224 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4225 IDLoc, Out, STI))
4226 return true;
4227 }
4228
4229 if (DoMove)
4230 std::swap(DstReg, TmpReg);
4231
4232 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4233 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4234 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4235 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4236
4237 if (DoMove)
4238 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004239
4240 return false;
4241}
4242
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004243bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004244 MCStreamer &Out,
4245 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004246 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004247
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004248 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4249 assert(Inst.getOperand(0).isReg() &&
4250 Inst.getOperand(1).isReg() &&
4251 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004252
4253 unsigned ATReg = Mips::NoRegister;
4254 unsigned FinalDstReg = Mips::NoRegister;
4255 unsigned DstReg = Inst.getOperand(0).getReg();
4256 unsigned SrcReg = Inst.getOperand(1).getReg();
4257 int64_t ImmValue = Inst.getOperand(2).getImm();
4258
Simon Dardisaa208812017-02-24 14:34:32 +00004259 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004260
4261 unsigned FinalOpcode = Inst.getOpcode();
4262
4263 if (DstReg == SrcReg) {
4264 ATReg = getATReg(Inst.getLoc());
4265 if (!ATReg)
4266 return true;
4267 FinalDstReg = DstReg;
4268 DstReg = ATReg;
4269 }
4270
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004271 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004272 switch (FinalOpcode) {
4273 default:
4274 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004275 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004276 FinalOpcode = Mips::ADD;
4277 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004278 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004279 FinalOpcode = Mips::ADDu;
4280 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004281 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004282 FinalOpcode = Mips::AND;
4283 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004284 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004285 FinalOpcode = Mips::NOR;
4286 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004287 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004288 FinalOpcode = Mips::OR;
4289 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004290 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004291 FinalOpcode = Mips::SLT;
4292 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004293 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004294 FinalOpcode = Mips::SLTu;
4295 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004296 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004297 FinalOpcode = Mips::XOR;
4298 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004299 case Mips::ADDi_MM:
4300 FinalOpcode = Mips::ADD_MM;
4301 break;
4302 case Mips::ADDiu_MM:
4303 FinalOpcode = Mips::ADDu_MM;
4304 break;
4305 case Mips::ANDi_MM:
4306 FinalOpcode = Mips::AND_MM;
4307 break;
4308 case Mips::ORi_MM:
4309 FinalOpcode = Mips::OR_MM;
4310 break;
4311 case Mips::SLTi_MM:
4312 FinalOpcode = Mips::SLT_MM;
4313 break;
4314 case Mips::SLTiu_MM:
4315 FinalOpcode = Mips::SLTu_MM;
4316 break;
4317 case Mips::XORi_MM:
4318 FinalOpcode = Mips::XOR_MM;
4319 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004320 case Mips::ANDi64:
4321 FinalOpcode = Mips::AND64;
4322 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004323 case Mips::NORImm64:
4324 FinalOpcode = Mips::NOR64;
4325 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004326 case Mips::ORi64:
4327 FinalOpcode = Mips::OR64;
4328 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004329 case Mips::SLTImm64:
4330 FinalOpcode = Mips::SLT64;
4331 break;
4332 case Mips::SLTUImm64:
4333 FinalOpcode = Mips::SLTu64;
4334 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004335 case Mips::XORi64:
4336 FinalOpcode = Mips::XOR64;
4337 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004338 }
4339
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004340 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004341 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004342 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004343 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004344 return false;
4345 }
4346 return true;
4347}
4348
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004349bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4350 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004351 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004352 unsigned ATReg = Mips::NoRegister;
4353 unsigned DReg = Inst.getOperand(0).getReg();
4354 unsigned SReg = Inst.getOperand(1).getReg();
4355 unsigned TReg = Inst.getOperand(2).getReg();
4356 unsigned TmpReg = DReg;
4357
4358 unsigned FirstShift = Mips::NOP;
4359 unsigned SecondShift = Mips::NOP;
4360
4361 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004362 if (DReg == SReg) {
4363 TmpReg = getATReg(Inst.getLoc());
4364 if (!TmpReg)
4365 return true;
4366 }
4367
4368 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004369 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4370 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004371 return false;
4372 }
4373
4374 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004375 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004376 return false;
4377 }
4378
4379 return true;
4380 }
4381
4382 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004383 switch (Inst.getOpcode()) {
4384 default:
4385 llvm_unreachable("unexpected instruction opcode");
4386 case Mips::ROL:
4387 FirstShift = Mips::SRLV;
4388 SecondShift = Mips::SLLV;
4389 break;
4390 case Mips::ROR:
4391 FirstShift = Mips::SLLV;
4392 SecondShift = Mips::SRLV;
4393 break;
4394 }
4395
4396 ATReg = getATReg(Inst.getLoc());
4397 if (!ATReg)
4398 return true;
4399
Daniel Sandersa736b372016-04-29 13:33:12 +00004400 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4401 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4402 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4403 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004404
4405 return false;
4406 }
4407
4408 return true;
4409}
4410
4411bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004412 MCStreamer &Out,
4413 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004414 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004415 unsigned ATReg = Mips::NoRegister;
4416 unsigned DReg = Inst.getOperand(0).getReg();
4417 unsigned SReg = Inst.getOperand(1).getReg();
4418 int64_t ImmValue = Inst.getOperand(2).getImm();
4419
4420 unsigned FirstShift = Mips::NOP;
4421 unsigned SecondShift = Mips::NOP;
4422
4423 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004424 if (Inst.getOpcode() == Mips::ROLImm) {
4425 uint64_t MaxShift = 32;
4426 uint64_t ShiftValue = ImmValue;
4427 if (ImmValue != 0)
4428 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004429 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004430 return false;
4431 }
4432
4433 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004434 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004435 return false;
4436 }
4437
4438 return true;
4439 }
4440
4441 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004442 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004443 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004444 return false;
4445 }
4446
4447 switch (Inst.getOpcode()) {
4448 default:
4449 llvm_unreachable("unexpected instruction opcode");
4450 case Mips::ROLImm:
4451 FirstShift = Mips::SLL;
4452 SecondShift = Mips::SRL;
4453 break;
4454 case Mips::RORImm:
4455 FirstShift = Mips::SRL;
4456 SecondShift = Mips::SLL;
4457 break;
4458 }
4459
4460 ATReg = getATReg(Inst.getLoc());
4461 if (!ATReg)
4462 return true;
4463
Daniel Sandersa736b372016-04-29 13:33:12 +00004464 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4465 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4466 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004467
4468 return false;
4469 }
4470
4471 return true;
4472}
4473
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004474bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4475 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004476 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004477 unsigned ATReg = Mips::NoRegister;
4478 unsigned DReg = Inst.getOperand(0).getReg();
4479 unsigned SReg = Inst.getOperand(1).getReg();
4480 unsigned TReg = Inst.getOperand(2).getReg();
4481 unsigned TmpReg = DReg;
4482
4483 unsigned FirstShift = Mips::NOP;
4484 unsigned SecondShift = Mips::NOP;
4485
4486 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004487 if (TmpReg == SReg) {
4488 TmpReg = getATReg(Inst.getLoc());
4489 if (!TmpReg)
4490 return true;
4491 }
4492
4493 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004494 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4495 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004496 return false;
4497 }
4498
4499 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004500 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004501 return false;
4502 }
4503
4504 return true;
4505 }
4506
4507 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004508 switch (Inst.getOpcode()) {
4509 default:
4510 llvm_unreachable("unexpected instruction opcode");
4511 case Mips::DROL:
4512 FirstShift = Mips::DSRLV;
4513 SecondShift = Mips::DSLLV;
4514 break;
4515 case Mips::DROR:
4516 FirstShift = Mips::DSLLV;
4517 SecondShift = Mips::DSRLV;
4518 break;
4519 }
4520
4521 ATReg = getATReg(Inst.getLoc());
4522 if (!ATReg)
4523 return true;
4524
Daniel Sandersa736b372016-04-29 13:33:12 +00004525 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4526 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4527 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4528 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004529
4530 return false;
4531 }
4532
4533 return true;
4534}
4535
4536bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004537 MCStreamer &Out,
4538 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004539 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004540 unsigned ATReg = Mips::NoRegister;
4541 unsigned DReg = Inst.getOperand(0).getReg();
4542 unsigned SReg = Inst.getOperand(1).getReg();
4543 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4544
4545 unsigned FirstShift = Mips::NOP;
4546 unsigned SecondShift = Mips::NOP;
4547
4548 MCInst TmpInst;
4549
4550 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004551 unsigned FinalOpcode = Mips::NOP;
4552 if (ImmValue == 0)
4553 FinalOpcode = Mips::DROTR;
4554 else if (ImmValue % 32 == 0)
4555 FinalOpcode = Mips::DROTR32;
4556 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4557 if (Inst.getOpcode() == Mips::DROLImm)
4558 FinalOpcode = Mips::DROTR32;
4559 else
4560 FinalOpcode = Mips::DROTR;
4561 } else if (ImmValue >= 33) {
4562 if (Inst.getOpcode() == Mips::DROLImm)
4563 FinalOpcode = Mips::DROTR;
4564 else
4565 FinalOpcode = Mips::DROTR32;
4566 }
4567
4568 uint64_t ShiftValue = ImmValue % 32;
4569 if (Inst.getOpcode() == Mips::DROLImm)
4570 ShiftValue = (32 - ImmValue % 32) % 32;
4571
Daniel Sandersa736b372016-04-29 13:33:12 +00004572 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004573
4574 return false;
4575 }
4576
4577 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004578 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004579 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004580 return false;
4581 }
4582
4583 switch (Inst.getOpcode()) {
4584 default:
4585 llvm_unreachable("unexpected instruction opcode");
4586 case Mips::DROLImm:
4587 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4588 FirstShift = Mips::DSLL;
4589 SecondShift = Mips::DSRL32;
4590 }
4591 if (ImmValue == 32) {
4592 FirstShift = Mips::DSLL32;
4593 SecondShift = Mips::DSRL32;
4594 }
4595 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4596 FirstShift = Mips::DSLL32;
4597 SecondShift = Mips::DSRL;
4598 }
4599 break;
4600 case Mips::DRORImm:
4601 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4602 FirstShift = Mips::DSRL;
4603 SecondShift = Mips::DSLL32;
4604 }
4605 if (ImmValue == 32) {
4606 FirstShift = Mips::DSRL32;
4607 SecondShift = Mips::DSLL32;
4608 }
4609 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4610 FirstShift = Mips::DSRL32;
4611 SecondShift = Mips::DSLL;
4612 }
4613 break;
4614 }
4615
4616 ATReg = getATReg(Inst.getLoc());
4617 if (!ATReg)
4618 return true;
4619
Daniel Sandersa736b372016-04-29 13:33:12 +00004620 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4621 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4622 Inst.getLoc(), STI);
4623 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004624
4625 return false;
4626 }
4627
4628 return true;
4629}
4630
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004631bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4632 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004633 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004634 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4635 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4636
Daniel Sandersa736b372016-04-29 13:33:12 +00004637 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004638 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004639 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004640 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004641 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4642 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004643
4644 return false;
4645}
4646
Simon Dardis3c82a642017-02-08 16:25:05 +00004647bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4648 const MCSubtargetInfo *STI) {
4649 MipsTargetStreamer &TOut = getTargetStreamer();
4650 unsigned ATReg = Mips::NoRegister;
4651 unsigned DstReg = Inst.getOperand(0).getReg();
4652 unsigned SrcReg = Inst.getOperand(1).getReg();
4653 int32_t ImmValue = Inst.getOperand(2).getImm();
4654
4655 ATReg = getATReg(IDLoc);
4656 if (!ATReg)
4657 return true;
4658
4659 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI);
4660
4661 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4662 SrcReg, ATReg, IDLoc, STI);
4663
4664 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4665
4666 return false;
4667}
4668
4669bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4670 const MCSubtargetInfo *STI) {
4671 MipsTargetStreamer &TOut = getTargetStreamer();
4672 unsigned ATReg = Mips::NoRegister;
4673 unsigned DstReg = Inst.getOperand(0).getReg();
4674 unsigned SrcReg = Inst.getOperand(1).getReg();
4675 unsigned TmpReg = Inst.getOperand(2).getReg();
4676
4677 ATReg = getATReg(Inst.getLoc());
4678 if (!ATReg)
4679 return true;
4680
4681 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4682 SrcReg, TmpReg, IDLoc, STI);
4683
4684 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4685
4686 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4687 DstReg, DstReg, 0x1F, IDLoc, STI);
4688
4689 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4690
4691 if (useTraps()) {
4692 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4693 } else {
4694 MCContext & Context = TOut.getStreamer().getContext();
4695 MCSymbol * BrTarget = Context.createTempSymbol();
4696 MCOperand LabelOp =
4697 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4698
4699 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4700 if (AssemblerOptions.back()->isReorder())
4701 TOut.emitNop(IDLoc, STI);
4702 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4703
4704 TOut.getStreamer().EmitLabel(BrTarget);
4705 }
4706 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4707
4708 return false;
4709}
4710
4711bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4712 const MCSubtargetInfo *STI) {
4713 MipsTargetStreamer &TOut = getTargetStreamer();
4714 unsigned ATReg = Mips::NoRegister;
4715 unsigned DstReg = Inst.getOperand(0).getReg();
4716 unsigned SrcReg = Inst.getOperand(1).getReg();
4717 unsigned TmpReg = Inst.getOperand(2).getReg();
4718
4719 ATReg = getATReg(IDLoc);
4720 if (!ATReg)
4721 return true;
4722
4723 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4724 SrcReg, TmpReg, IDLoc, STI);
4725
4726 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4727 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4728 if (useTraps()) {
4729 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4730 } else {
4731 MCContext & Context = TOut.getStreamer().getContext();
4732 MCSymbol * BrTarget = Context.createTempSymbol();
4733 MCOperand LabelOp =
4734 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4735
4736 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4737 if (AssemblerOptions.back()->isReorder())
4738 TOut.emitNop(IDLoc, STI);
4739 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4740
4741 TOut.getStreamer().EmitLabel(BrTarget);
4742 }
4743
4744 return false;
4745}
4746
4747bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4748 const MCSubtargetInfo *STI) {
4749 MipsTargetStreamer &TOut = getTargetStreamer();
4750 unsigned DstReg = Inst.getOperand(0).getReg();
4751 unsigned SrcReg = Inst.getOperand(1).getReg();
4752 unsigned TmpReg = Inst.getOperand(2).getReg();
4753
4754 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4755 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4756
4757 return false;
4758}
4759
Simon Dardisaff4d142016-10-18 14:28:00 +00004760// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4761// lw $<reg+1>>, offset+4($reg2)'
4762// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4763// sw $<reg+1>>, offset+4($reg2)'
4764// for O32.
4765bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4766 MCStreamer &Out,
4767 const MCSubtargetInfo *STI,
4768 bool IsLoad) {
4769 if (!isABI_O32())
4770 return true;
4771
4772 warnIfNoMacro(IDLoc);
4773
4774 MipsTargetStreamer &TOut = getTargetStreamer();
4775 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4776 unsigned FirstReg = Inst.getOperand(0).getReg();
4777 unsigned SecondReg = nextReg(FirstReg);
4778 unsigned BaseReg = Inst.getOperand(1).getReg();
4779 if (!SecondReg)
4780 return true;
4781
4782 warnIfRegIndexIsAT(FirstReg, IDLoc);
4783
4784 assert(Inst.getOperand(2).isImm() &&
4785 "Offset for load macro is not immediate!");
4786
4787 MCOperand &FirstOffset = Inst.getOperand(2);
4788 signed NextOffset = FirstOffset.getImm() + 4;
4789 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4790
4791 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4792 return true;
4793
4794 // For loads, clobber the base register with the second load instead of the
4795 // first if the BaseReg == FirstReg.
4796 if (FirstReg != BaseReg || !IsLoad) {
4797 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4798 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4799 } else {
4800 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4801 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4802 }
4803
4804 return false;
4805}
4806
Simon Dardis43115a12016-11-21 20:30:41 +00004807bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4808 const MCSubtargetInfo *STI) {
4809
4810 warnIfNoMacro(IDLoc);
4811 MipsTargetStreamer &TOut = getTargetStreamer();
4812
4813 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4814 Inst.getOperand(2).getReg() != Mips::ZERO) {
4815 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4816 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4817 IDLoc, STI);
4818 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4819 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4820 return false;
4821 }
4822
4823 unsigned Reg = 0;
4824 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4825 Reg = Inst.getOperand(2).getReg();
4826 } else {
4827 Reg = Inst.getOperand(1).getReg();
4828 }
4829 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4830 return false;
4831}
4832
4833bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4834 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004835 warnIfNoMacro(IDLoc);
4836 MipsTargetStreamer &TOut = getTargetStreamer();
4837
4838 unsigned Opc;
4839 int64_t Imm = Inst.getOperand(2).getImm();
4840 unsigned Reg = Inst.getOperand(1).getReg();
4841
4842 if (Imm == 0) {
4843 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4844 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4845 return false;
4846 } else {
4847
4848 if (Reg == Mips::ZERO) {
4849 Warning(IDLoc, "comparison is always false");
4850 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4851 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4852 return false;
4853 }
4854
4855 if (Imm > -0x8000 && Imm < 0) {
4856 Imm = -Imm;
4857 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4858 } else {
4859 Opc = Mips::XORi;
4860 }
4861 }
4862 if (!isUInt<16>(Imm)) {
4863 unsigned ATReg = getATReg(IDLoc);
4864 if (!ATReg)
4865 return true;
4866
4867 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4868 Out, STI))
4869 return true;
4870
4871 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4872 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4873 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4874 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4875 return false;
4876 }
4877
4878 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4879 Imm, IDLoc, STI);
4880 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4881 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4882 return false;
4883}
4884
Daniel Sandersc5537422016-07-27 13:49:44 +00004885unsigned
4886MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
4887 const OperandVector &Operands) {
4888 switch (Inst.getOpcode()) {
4889 default:
4890 return Match_Success;
4891 case Mips::DATI:
4892 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00004893 case Mips::DATI_MM64R6:
4894 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00004895 if (static_cast<MipsOperand &>(*Operands[1])
4896 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
4897 return Match_Success;
4898 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00004899 }
4900}
Simon Dardis730fdb72017-01-16 13:55:58 +00004901
Matheus Almeida595fcab2014-06-11 15:05:56 +00004902unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00004903 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00004904 // As described by the MIPSR6 spec, daui must not use the zero operand for
4905 // its source operand.
4906 case Mips::DAUI:
4907 case Mips::DAUI_MM64R6:
4908 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4909 Inst.getOperand(1).getReg() == Mips::ZERO_64)
4910 return Match_RequiresNoZeroRegister;
4911 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00004912 // As described by the Mips32r2 spec, the registers Rd and Rs for
4913 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00004914 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00004915 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00004916 case Mips::JALR_HB:
4917 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00004918 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00004919 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4920 return Match_RequiresDifferentSrcAndDst;
4921 return Match_Success;
4922 case Mips::LWP_MM:
4923 case Mips::LWP_MMR6:
4924 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
4925 return Match_RequiresDifferentSrcAndDst;
4926 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00004927 case Mips::SYNC:
4928 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
4929 return Match_NonZeroOperandForSync;
4930 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004931 // As described the MIPSR6 spec, the compact branches that compare registers
4932 // must:
4933 // a) Not use the zero register.
4934 // b) Not use the same register twice.
4935 // c) rs < rt for bnec, beqc.
4936 // NB: For this case, the encoding will swap the operands as their
4937 // ordering doesn't matter. GAS performs this transformation too.
4938 // Hence, that constraint does not have to be enforced.
4939 //
4940 // The compact branches that branch iff the signed addition of two registers
4941 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
4942 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004943 case Mips::BLEZC: case Mips::BLEZC_MMR6:
4944 case Mips::BGEZC: case Mips::BGEZC_MMR6:
4945 case Mips::BGTZC: case Mips::BGTZC_MMR6:
4946 case Mips::BLTZC: case Mips::BLTZC_MMR6:
4947 case Mips::BEQZC: case Mips::BEQZC_MMR6:
4948 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004949 case Mips::BLEZC64:
4950 case Mips::BGEZC64:
4951 case Mips::BGTZC64:
4952 case Mips::BLTZC64:
4953 case Mips::BEQZC64:
4954 case Mips::BNEZC64:
4955 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4956 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004957 return Match_RequiresNoZeroRegister;
4958 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004959 case Mips::BGEC: case Mips::BGEC_MMR6:
4960 case Mips::BLTC: case Mips::BLTC_MMR6:
4961 case Mips::BGEUC: case Mips::BGEUC_MMR6:
4962 case Mips::BLTUC: case Mips::BLTUC_MMR6:
4963 case Mips::BEQC: case Mips::BEQC_MMR6:
4964 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004965 case Mips::BGEC64:
4966 case Mips::BLTC64:
4967 case Mips::BGEUC64:
4968 case Mips::BLTUC64:
4969 case Mips::BEQC64:
4970 case Mips::BNEC64:
4971 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4972 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004973 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00004974 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4975 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004976 return Match_RequiresNoZeroRegister;
4977 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4978 return Match_RequiresDifferentOperands;
4979 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004980 }
Simon Dardis730fdb72017-01-16 13:55:58 +00004981
4982 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
4983 if ((TSFlags & MipsII::HasFCCRegOperand) &&
4984 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
4985 return Match_NoFCCRegisterForCurrentISA;
4986
4987 return Match_Success;
4988
Matheus Almeida595fcab2014-06-11 15:05:56 +00004989}
4990
Daniel Sanders52da7af2015-11-06 12:11:03 +00004991static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
4992 uint64_t ErrorInfo) {
4993 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
4994 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
4995 if (ErrorLoc == SMLoc())
4996 return Loc;
4997 return ErrorLoc;
4998 }
4999 return Loc;
5000}
5001
David Blaikie960ea3f2014-06-08 16:18:35 +00005002bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5003 OperandVector &Operands,
5004 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005005 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005006 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005007 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005008 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005009 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005010
5011 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005012 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005013 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005014 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005015 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005016 case Match_MissingFeature:
5017 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5018 return true;
5019 case Match_InvalidOperand: {
5020 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005021 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005022 if (ErrorInfo >= Operands.size())
5023 return Error(IDLoc, "too few operands for instruction");
5024
Daniel Sanders52da7af2015-11-06 12:11:03 +00005025 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005026 if (ErrorLoc == SMLoc())
5027 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005028 }
5029
5030 return Error(ErrorLoc, "invalid operand for instruction");
5031 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005032 case Match_NonZeroOperandForSync:
5033 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005034 case Match_MnemonicFail:
5035 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005036 case Match_RequiresDifferentSrcAndDst:
5037 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005038 case Match_RequiresDifferentOperands:
5039 return Error(IDLoc, "registers must be different");
5040 case Match_RequiresNoZeroRegister:
5041 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005042 case Match_RequiresSameSrcAndDst:
5043 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005044 case Match_NoFCCRegisterForCurrentISA:
5045 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5046 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005047 case Match_Immz:
5048 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005049 case Match_UImm1_0:
5050 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5051 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005052 case Match_UImm2_0:
5053 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5054 "expected 2-bit unsigned immediate");
5055 case Match_UImm2_1:
5056 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5057 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005058 case Match_UImm3_0:
5059 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5060 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005061 case Match_UImm4_0:
5062 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5063 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005064 case Match_SImm4_0:
5065 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5066 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005067 case Match_UImm5_0:
5068 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5069 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005070 case Match_SImm5_0:
5071 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5072 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005073 case Match_UImm5_1:
5074 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5075 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005076 case Match_UImm5_32:
5077 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5078 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005079 case Match_UImm5_33:
5080 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5081 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005082 case Match_UImm5_0_Report_UImm6:
5083 // This is used on UImm5 operands that have a corresponding UImm5_32
5084 // operand to avoid confusing the user.
5085 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5086 "expected 6-bit unsigned immediate");
5087 case Match_UImm5_Lsl2:
5088 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5089 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005090 case Match_UImmRange2_64:
5091 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5092 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005093 case Match_UImm6_0:
5094 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5095 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005096 case Match_UImm6_Lsl2:
5097 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5098 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005099 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005100 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5101 "expected 6-bit signed immediate");
5102 case Match_UImm7_0:
5103 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5104 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005105 case Match_UImm7_N1:
5106 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5107 "expected immediate in range -1 .. 126");
5108 case Match_SImm7_Lsl2:
5109 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5110 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005111 case Match_UImm8_0:
5112 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5113 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005114 case Match_UImm10_0:
5115 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5116 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005117 case Match_SImm10_0:
5118 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5119 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005120 case Match_SImm11_0:
5121 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5122 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005123 case Match_UImm16:
5124 case Match_UImm16_Relaxed:
5125 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5126 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005127 case Match_SImm16:
5128 case Match_SImm16_Relaxed:
5129 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5130 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005131 case Match_SImm19_Lsl2:
5132 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5133 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005134 case Match_UImm20_0:
5135 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5136 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005137 case Match_UImm26_0:
5138 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5139 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005140 case Match_SImm32:
5141 case Match_SImm32_Relaxed:
5142 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5143 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005144 case Match_UImm32_Coerced:
5145 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5146 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005147 case Match_MemSImm9:
5148 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5149 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005150 case Match_MemSImm10:
5151 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5152 "expected memory with 10-bit signed offset");
5153 case Match_MemSImm10Lsl1:
5154 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5155 "expected memory with 11-bit signed offset and multiple of 2");
5156 case Match_MemSImm10Lsl2:
5157 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5158 "expected memory with 12-bit signed offset and multiple of 4");
5159 case Match_MemSImm10Lsl3:
5160 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5161 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005162 case Match_MemSImm11:
5163 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5164 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005165 case Match_MemSImm12:
5166 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5167 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005168 case Match_MemSImm16:
5169 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5170 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00005171 }
Craig Topper589ceee2015-01-03 08:16:34 +00005172
5173 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005174}
5175
Toma Tabacud9d344b2015-04-27 14:05:04 +00005176void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5177 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5178 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5179 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005180}
5181
Toma Tabacu81496c12015-05-20 08:54:45 +00005182void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5183 if (!AssemblerOptions.back()->isMacro())
5184 Warning(Loc, "macro instruction expanded into multiple instructions");
5185}
5186
Daniel Sandersef638fe2014-10-03 15:37:37 +00005187void
5188MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5189 SMRange Range, bool ShowColors) {
5190 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005191 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005192 ShowColors);
5193}
5194
Jack Carter1ac53222013-02-20 23:11:17 +00005195int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005196 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005197
Vladimir Medic4c299852013-11-06 11:27:05 +00005198 CC = StringSwitch<unsigned>(Name)
5199 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005200 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005201 .Case("a0", 4)
5202 .Case("a1", 5)
5203 .Case("a2", 6)
5204 .Case("a3", 7)
5205 .Case("v0", 2)
5206 .Case("v1", 3)
5207 .Case("s0", 16)
5208 .Case("s1", 17)
5209 .Case("s2", 18)
5210 .Case("s3", 19)
5211 .Case("s4", 20)
5212 .Case("s5", 21)
5213 .Case("s6", 22)
5214 .Case("s7", 23)
5215 .Case("k0", 26)
5216 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005217 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005218 .Case("sp", 29)
5219 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005220 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005221 .Case("ra", 31)
5222 .Case("t0", 8)
5223 .Case("t1", 9)
5224 .Case("t2", 10)
5225 .Case("t3", 11)
5226 .Case("t4", 12)
5227 .Case("t5", 13)
5228 .Case("t6", 14)
5229 .Case("t7", 15)
5230 .Case("t8", 24)
5231 .Case("t9", 25)
5232 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005233
Toma Tabacufda445c2014-09-15 15:33:01 +00005234 if (!(isABI_N32() || isABI_N64()))
5235 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005236
Daniel Sandersef638fe2014-10-03 15:37:37 +00005237 if (12 <= CC && CC <= 15) {
5238 // Name is one of t4-t7
5239 AsmToken RegTok = getLexer().peekTok();
5240 SMRange RegRange = RegTok.getLocRange();
5241
5242 StringRef FixedName = StringSwitch<StringRef>(Name)
5243 .Case("t4", "t0")
5244 .Case("t5", "t1")
5245 .Case("t6", "t2")
5246 .Case("t7", "t3")
5247 .Default("");
5248 assert(FixedName != "" && "Register name is not one of t4-t7.");
5249
5250 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5251 "Did you mean $" + FixedName + "?", RegRange);
5252 }
5253
Toma Tabacufda445c2014-09-15 15:33:01 +00005254 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5255 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5256 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5257 if (8 <= CC && CC <= 11)
5258 CC += 4;
5259
5260 if (CC == -1)
5261 CC = StringSwitch<unsigned>(Name)
5262 .Case("a4", 8)
5263 .Case("a5", 9)
5264 .Case("a6", 10)
5265 .Case("a7", 11)
5266 .Case("kt0", 26)
5267 .Case("kt1", 27)
5268 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005269
5270 return CC;
5271}
Jack Carterd0bd6422013-04-18 00:41:53 +00005272
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005273int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5274 int CC;
5275
5276 CC = StringSwitch<unsigned>(Name)
5277 .Case("hwr_cpunum", 0)
5278 .Case("hwr_synci_step", 1)
5279 .Case("hwr_cc", 2)
5280 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005281 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005282 .Default(-1);
5283
5284 return CC;
5285}
5286
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005287int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005288 if (Name[0] == 'f') {
5289 StringRef NumString = Name.substr(1);
5290 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005291 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005292 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005293 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005294 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005295 return IntVal;
5296 }
5297 return -1;
5298}
Jack Cartera63b16a2012-09-07 00:23:42 +00005299
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005300int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005301 if (Name.startswith("fcc")) {
5302 StringRef NumString = Name.substr(3);
5303 unsigned IntVal;
5304 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005305 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005306 if (IntVal > 7) // There are only 8 fcc registers.
5307 return -1;
5308 return IntVal;
5309 }
5310 return -1;
5311}
5312
5313int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005314 if (Name.startswith("ac")) {
5315 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005316 unsigned IntVal;
5317 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005318 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005319 if (IntVal > 3) // There are only 3 acc registers.
5320 return -1;
5321 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005322 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005323 return -1;
5324}
Jack Carterd0bd6422013-04-18 00:41:53 +00005325
Jack Carter5dc8ac92013-09-25 23:50:44 +00005326int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5327 unsigned IntVal;
5328
5329 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5330 return -1;
5331
5332 if (IntVal > 31)
5333 return -1;
5334
5335 return IntVal;
5336}
5337
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005338int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5339 int CC;
5340
5341 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005342 .Case("msair", 0)
5343 .Case("msacsr", 1)
5344 .Case("msaaccess", 2)
5345 .Case("msasave", 3)
5346 .Case("msamodify", 4)
5347 .Case("msarequest", 5)
5348 .Case("msamap", 6)
5349 .Case("msaunmap", 7)
5350 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005351
5352 return CC;
5353}
5354
Simon Dardis3aa8a902017-02-06 12:43:46 +00005355bool MipsAsmParser::canUseATReg() {
5356 return AssemblerOptions.back()->getATRegIndex() != 0;
5357}
5358
Toma Tabacu89a712b2015-04-15 10:48:56 +00005359unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005360 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005361 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005362 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005363 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005364 return 0;
5365 }
5366 unsigned AT = getReg(
5367 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005368 return AT;
5369}
Jack Carter0b744b32012-10-04 02:29:46 +00005370
Jack Carterd0bd6422013-04-18 00:41:53 +00005371unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005372 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005373}
5374
Toma Tabacu13964452014-09-04 13:23:44 +00005375bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005376 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005377 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005378
Jack Carter30a59822012-10-04 04:03:53 +00005379 // Check if the current operand has a custom associated parser, if so, try to
5380 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005381 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5382 if (ResTy == MatchOperand_Success)
5383 return false;
5384 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5385 // there was a match, but an error occurred, in which case, just return that
5386 // the operand parsing failed.
5387 if (ResTy == MatchOperand_ParseFail)
5388 return true;
5389
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005390 DEBUG(dbgs() << ".. Generic Parser\n");
5391
Jack Carterb4dbc172012-09-05 23:34:03 +00005392 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005393 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005394 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005395 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005396
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005397 // Almost all registers have been parsed by custom parsers. There is only
5398 // one exception to this. $zero (and it's alias $0) will reach this point
5399 // for div, divu, and similar instructions because it is not an operand
5400 // to the instruction definition but an explicit register. Special case
5401 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005402 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005403 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005404
Jack Carterd0bd6422013-04-18 00:41:53 +00005405 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005406 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005407 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005408 return true;
5409
Jack Carter873c7242013-01-12 01:03:14 +00005410 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005411 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005412 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005413 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005414 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005415
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005416 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005417 return false;
5418 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005419 default: {
5420 DEBUG(dbgs() << ".. generic integer expression\n");
5421
5422 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005423 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005424 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005425 return true;
5426
Jack Carter873c7242013-01-12 01:03:14 +00005427 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5428
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005429 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005430 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005431 }
Jack Carter0b744b32012-10-04 02:29:46 +00005432 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005433 return true;
5434}
5435
Jack Carterb5cf5902013-04-17 00:18:04 +00005436bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005437 switch (Expr->getKind()) {
5438 case MCExpr::Constant:
5439 return true;
5440 case MCExpr::SymbolRef:
5441 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
Simon Dardisc6be2252017-08-09 10:47:52 +00005442 case MCExpr::Binary: {
5443 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
5444 assert(BE && "Binary expression is not a binary expression?");
5445 if (!isEvaluated(BE->getLHS()))
5446 return false;
5447 return isEvaluated(BE->getRHS());
5448 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005449 case MCExpr::Unary:
5450 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005451 case MCExpr::Target:
5452 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005453 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005454 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005455}
Jack Carterd0bd6422013-04-18 00:41:53 +00005456
Jack Carterb4dbc172012-09-05 23:34:03 +00005457bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5458 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005459 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005460 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005461 if (ResTy == MatchOperand_Success) {
5462 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005463 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005464 StartLoc = Operand.getStartLoc();
5465 EndLoc = Operand.getEndLoc();
5466
5467 // AFAIK, we only support numeric registers and named GPR's in CFI
5468 // directives.
5469 // Don't worry about eating tokens before failing. Using an unrecognised
5470 // register is a parse error.
5471 if (Operand.isGPRAsmReg()) {
5472 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005473 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005474 }
5475
5476 return (RegNo == (unsigned)-1);
5477 }
5478
5479 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005480 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005481}
5482
Jack Carterb5cf5902013-04-17 00:18:04 +00005483bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005484 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005485
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005486 if (isParenExpr)
5487 return getParser().parseParenExprOfDepth(0, Res, S);
5488 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005489}
5490
Alex Bradbury58eba092016-11-01 16:32:05 +00005491OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005492MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005493 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005494 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005495 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005496 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005497 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005498 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005499 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005500 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005501
Jack Carterb5cf5902013-04-17 00:18:04 +00005502 if (getLexer().getKind() == AsmToken::LParen) {
5503 Parser.Lex();
5504 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005505 }
5506
Jack Carterb5cf5902013-04-17 00:18:04 +00005507 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005508 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005509 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005510
Jack Carterd0bd6422013-04-18 00:41:53 +00005511 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005512 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005513 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005514 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005515 SMLoc E =
5516 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005517 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005518 return MatchOperand_Success;
5519 }
5520 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005521 SMLoc E =
5522 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005523
Jack Carterd0bd6422013-04-18 00:41:53 +00005524 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005525 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005526 auto Base = MipsOperand::createGPRReg(
5527 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005528 Operands.push_back(
5529 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005530 return MatchOperand_Success;
5531 }
Simon Dardis858915f2016-10-18 15:17:17 +00005532 MCBinaryExpr::Opcode Opcode;
5533 // GAS and LLVM treat comparison operators different. GAS will generate -1
5534 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5535 // highly unlikely to be found in a memory offset expression, we don't
5536 // handle them.
5537 switch (Tok.getKind()) {
5538 case AsmToken::Plus:
5539 Opcode = MCBinaryExpr::Add;
5540 Parser.Lex();
5541 break;
5542 case AsmToken::Minus:
5543 Opcode = MCBinaryExpr::Sub;
5544 Parser.Lex();
5545 break;
5546 case AsmToken::Star:
5547 Opcode = MCBinaryExpr::Mul;
5548 Parser.Lex();
5549 break;
5550 case AsmToken::Pipe:
5551 Opcode = MCBinaryExpr::Or;
5552 Parser.Lex();
5553 break;
5554 case AsmToken::Amp:
5555 Opcode = MCBinaryExpr::And;
5556 Parser.Lex();
5557 break;
5558 case AsmToken::LessLess:
5559 Opcode = MCBinaryExpr::Shl;
5560 Parser.Lex();
5561 break;
5562 case AsmToken::GreaterGreater:
5563 Opcode = MCBinaryExpr::LShr;
5564 Parser.Lex();
5565 break;
5566 case AsmToken::Caret:
5567 Opcode = MCBinaryExpr::Xor;
5568 Parser.Lex();
5569 break;
5570 case AsmToken::Slash:
5571 Opcode = MCBinaryExpr::Div;
5572 Parser.Lex();
5573 break;
5574 case AsmToken::Percent:
5575 Opcode = MCBinaryExpr::Mod;
5576 Parser.Lex();
5577 break;
5578 default:
5579 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5580 return MatchOperand_ParseFail;
5581 }
5582 const MCExpr * NextExpr;
5583 if (getParser().parseExpression(NextExpr))
5584 return MatchOperand_ParseFail;
5585 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005586 }
5587
Jack Carterd0bd6422013-04-18 00:41:53 +00005588 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005589 }
5590
Toma Tabacu13964452014-09-04 13:23:44 +00005591 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005592 if (Res != MatchOperand_Success)
5593 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005594
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005595 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005596 Error(Parser.getTok().getLoc(), "')' expected");
5597 return MatchOperand_ParseFail;
5598 }
5599
Jack Carter873c7242013-01-12 01:03:14 +00005600 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5601
Jack Carterd0bd6422013-04-18 00:41:53 +00005602 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005603
Craig Topper062a2ba2014-04-25 05:30:21 +00005604 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005605 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005606
Jack Carterd0bd6422013-04-18 00:41:53 +00005607 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005608 std::unique_ptr<MipsOperand> op(
5609 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005610 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005611 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005612 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005613 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005614 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5615 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005616 if (IdVal->evaluateAsAbsolute(Imm))
5617 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005618 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005619 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005620 getContext());
5621 }
5622
David Blaikie960ea3f2014-06-08 16:18:35 +00005623 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005624 return MatchOperand_Success;
5625}
5626
David Blaikie960ea3f2014-06-08 16:18:35 +00005627bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005628 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005629 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00005630 if (Sym) {
5631 SMLoc S = Parser.getTok().getLoc();
5632 const MCExpr *Expr;
5633 if (Sym->isVariable())
5634 Expr = Sym->getVariableValue();
5635 else
5636 return false;
5637 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005638 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005639 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005640 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005641 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005642 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005643 if (ResTy == MatchOperand_Success) {
5644 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005645 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00005646 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005647 llvm_unreachable("Should never ParseFail");
5648 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00005649 }
Jack Carterd76b2372013-03-21 21:44:16 +00005650 }
5651 }
5652 return false;
5653}
Jack Carterd0bd6422013-04-18 00:41:53 +00005654
Alex Bradbury58eba092016-11-01 16:32:05 +00005655OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005656MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00005657 StringRef Identifier,
5658 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005659 int Index = matchCPURegisterName(Identifier);
5660 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005661 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005662 Index, Identifier, getContext().getRegisterInfo(), S,
5663 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005664 return MatchOperand_Success;
5665 }
5666
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005667 Index = matchHWRegsRegisterName(Identifier);
5668 if (Index != -1) {
5669 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005670 Index, Identifier, getContext().getRegisterInfo(), S,
5671 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005672 return MatchOperand_Success;
5673 }
5674
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005675 Index = matchFPURegisterName(Identifier);
5676 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005677 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005678 Index, Identifier, getContext().getRegisterInfo(), S,
5679 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005680 return MatchOperand_Success;
5681 }
5682
5683 Index = matchFCCRegisterName(Identifier);
5684 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005685 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005686 Index, Identifier, getContext().getRegisterInfo(), S,
5687 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005688 return MatchOperand_Success;
5689 }
5690
5691 Index = matchACRegisterName(Identifier);
5692 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005693 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005694 Index, Identifier, getContext().getRegisterInfo(), S,
5695 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005696 return MatchOperand_Success;
5697 }
5698
5699 Index = matchMSA128RegisterName(Identifier);
5700 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005701 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005702 Index, Identifier, getContext().getRegisterInfo(), S,
5703 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005704 return MatchOperand_Success;
5705 }
5706
5707 Index = matchMSA128CtrlRegisterName(Identifier);
5708 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005709 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005710 Index, Identifier, getContext().getRegisterInfo(), S,
5711 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005712 return MatchOperand_Success;
5713 }
5714
5715 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00005716}
5717
Alex Bradbury58eba092016-11-01 16:32:05 +00005718OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005719MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005720 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00005721 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005722
5723 if (Token.is(AsmToken::Identifier)) {
5724 DEBUG(dbgs() << ".. identifier\n");
5725 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00005726 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005727 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00005728 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005729 } else if (Token.is(AsmToken::Integer)) {
5730 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00005731 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005732 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
5733 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005734 return MatchOperand_Success;
5735 }
5736
5737 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
5738
5739 return MatchOperand_NoMatch;
5740}
5741
Alex Bradbury58eba092016-11-01 16:32:05 +00005742OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005743MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005744 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005745 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005746
5747 auto Token = Parser.getTok();
5748
5749 SMLoc S = Token.getLoc();
5750
5751 if (Token.isNot(AsmToken::Dollar)) {
5752 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
5753 if (Token.is(AsmToken::Identifier)) {
5754 if (searchSymbolAlias(Operands))
5755 return MatchOperand_Success;
5756 }
5757 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
5758 return MatchOperand_NoMatch;
5759 }
5760 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005761
Toma Tabacu13964452014-09-04 13:23:44 +00005762 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00005763 if (ResTy == MatchOperand_Success) {
5764 Parser.Lex(); // $
5765 Parser.Lex(); // identifier
5766 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005767 return ResTy;
5768}
5769
Alex Bradbury58eba092016-11-01 16:32:05 +00005770OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005771MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005772 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005773 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005774
5775 SMLoc S = getLexer().getLoc();
5776
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005777 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005778 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005779 if (ResTy != MatchOperand_NoMatch)
5780 return ResTy;
5781
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005782 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00005783 const MCExpr *Expr = nullptr;
5784 if (Parser.parseExpression(Expr)) {
5785 // We have no way of knowing if a symbol was consumed so we must ParseFail
5786 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005787 }
Daniel Sandersffd84362014-04-01 10:41:48 +00005788 Operands.push_back(
5789 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005790 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00005791}
5792
Alex Bradbury58eba092016-11-01 16:32:05 +00005793OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005794MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005795 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00005796 const MCExpr *IdVal;
5797 // If the first token is '$' we may have register operand.
5798 if (Parser.getTok().is(AsmToken::Dollar))
5799 return MatchOperand_NoMatch;
5800 SMLoc S = Parser.getTok().getLoc();
5801 if (getParser().parseExpression(IdVal))
5802 return MatchOperand_ParseFail;
5803 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00005804 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00005805 int64_t Val = MCE->getValue();
5806 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5807 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00005808 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00005809 return MatchOperand_Success;
5810}
5811
Alex Bradbury58eba092016-11-01 16:32:05 +00005812OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005813MipsAsmParser::parseRegisterList(OperandVector &Operands) {
5814 MCAsmParser &Parser = getParser();
5815 SmallVector<unsigned, 10> Regs;
5816 unsigned RegNo;
5817 unsigned PrevReg = Mips::NoRegister;
5818 bool RegRange = false;
5819 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5820
5821 if (Parser.getTok().isNot(AsmToken::Dollar))
5822 return MatchOperand_ParseFail;
5823
5824 SMLoc S = Parser.getTok().getLoc();
5825 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
5826 SMLoc E = getLexer().getLoc();
5827 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
5828 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
5829 if (RegRange) {
5830 // Remove last register operand because registers from register range
5831 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005832 if ((isGP64bit() && RegNo == Mips::RA_64) ||
5833 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005834 Regs.push_back(RegNo);
5835 } else {
5836 unsigned TmpReg = PrevReg + 1;
5837 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005838 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
5839 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
5840 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005841 Error(E, "invalid register operand");
5842 return MatchOperand_ParseFail;
5843 }
5844
5845 PrevReg = TmpReg;
5846 Regs.push_back(TmpReg++);
5847 }
5848 }
5849
5850 RegRange = false;
5851 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005852 if ((PrevReg == Mips::NoRegister) &&
5853 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
5854 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005855 Error(E, "$16 or $31 expected");
5856 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005857 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
5858 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
5859 !isGP64bit()) ||
5860 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
5861 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
5862 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005863 Error(E, "invalid register operand");
5864 return MatchOperand_ParseFail;
5865 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005866 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
5867 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
5868 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005869 Error(E, "consecutive register numbers expected");
5870 return MatchOperand_ParseFail;
5871 }
5872
5873 Regs.push_back(RegNo);
5874 }
5875
5876 if (Parser.getTok().is(AsmToken::Minus))
5877 RegRange = true;
5878
5879 if (!Parser.getTok().isNot(AsmToken::Minus) &&
5880 !Parser.getTok().isNot(AsmToken::Comma)) {
5881 Error(E, "',' or '-' expected");
5882 return MatchOperand_ParseFail;
5883 }
5884
5885 Lex(); // Consume comma or minus
5886 if (Parser.getTok().isNot(AsmToken::Dollar))
5887 break;
5888
5889 PrevReg = RegNo;
5890 }
5891
5892 SMLoc E = Parser.getTok().getLoc();
5893 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5894 parseMemOperand(Operands);
5895 return MatchOperand_Success;
5896}
5897
Alex Bradbury58eba092016-11-01 16:32:05 +00005898OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005899MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
5900 MCAsmParser &Parser = getParser();
5901
5902 SMLoc S = Parser.getTok().getLoc();
5903 if (parseAnyRegister(Operands) != MatchOperand_Success)
5904 return MatchOperand_ParseFail;
5905
5906 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00005907 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00005908
Benjamin Kramer2b68d152016-05-09 10:31:17 +00005909 Operands.pop_back();
5910 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005911 return MatchOperand_Success;
5912}
5913
Alex Bradbury58eba092016-11-01 16:32:05 +00005914OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00005915MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
5916 MCAsmParser &Parser = getParser();
5917 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5918 SmallVector<unsigned, 10> Regs;
5919
5920 if (Parser.getTok().isNot(AsmToken::Dollar))
5921 return MatchOperand_ParseFail;
5922
5923 SMLoc S = Parser.getTok().getLoc();
5924
5925 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5926 return MatchOperand_ParseFail;
5927
5928 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5929 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5930 Regs.push_back(RegNo);
5931
5932 SMLoc E = Parser.getTok().getLoc();
5933 if (Parser.getTok().isNot(AsmToken::Comma)) {
5934 Error(E, "',' expected");
5935 return MatchOperand_ParseFail;
5936 }
5937
5938 // Remove comma.
5939 Parser.Lex();
5940
5941 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5942 return MatchOperand_ParseFail;
5943
5944 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5945 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5946 Regs.push_back(RegNo);
5947
5948 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5949
5950 return MatchOperand_Success;
5951}
5952
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005953/// Sometimes (i.e. load/stores) the operand may be followed immediately by
5954/// either this.
5955/// ::= '(', register, ')'
5956/// handle it before we iterate so we don't get tripped up by the lack of
5957/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005958bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005959 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005960 if (getLexer().is(AsmToken::LParen)) {
5961 Operands.push_back(
5962 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
5963 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005964 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005965 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005966 return Error(Loc, "unexpected token in argument list");
5967 }
5968 if (Parser.getTok().isNot(AsmToken::RParen)) {
5969 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005970 return Error(Loc, "unexpected token, expected ')'");
5971 }
5972 Operands.push_back(
5973 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
5974 Parser.Lex();
5975 }
5976 return false;
5977}
5978
5979/// Sometimes (i.e. in MSA) the operand may be followed immediately by
5980/// either one of these.
5981/// ::= '[', register, ']'
5982/// ::= '[', integer, ']'
5983/// handle it before we iterate so we don't get tripped up by the lack of
5984/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005985bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00005986 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005987 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005988 if (getLexer().is(AsmToken::LBrac)) {
5989 Operands.push_back(
5990 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
5991 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005992 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005993 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005994 return Error(Loc, "unexpected token in argument list");
5995 }
5996 if (Parser.getTok().isNot(AsmToken::RBrac)) {
5997 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005998 return Error(Loc, "unexpected token, expected ']'");
5999 }
6000 Operands.push_back(
6001 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
6002 Parser.Lex();
6003 }
6004 return false;
6005}
6006
David Blaikie960ea3f2014-06-08 16:18:35 +00006007bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6008 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006009 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006010 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006011
6012 // We have reached first instruction, module directive are now forbidden.
6013 getTargetStreamer().forbidModuleDirective();
6014
Vladimir Medic74593e62013-07-17 15:00:42 +00006015 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006016 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006017 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00006018 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006019 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006020 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006021
6022 // Read the remaining operands.
6023 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6024 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006025 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006026 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006027 return Error(Loc, "unexpected token in argument list");
6028 }
Toma Tabacu13964452014-09-04 13:23:44 +00006029 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006030 return true;
6031 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006032
Jack Carterd0bd6422013-04-18 00:41:53 +00006033 while (getLexer().is(AsmToken::Comma)) {
6034 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006035 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006036 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006037 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006038 return Error(Loc, "unexpected token in argument list");
6039 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006040 // Parse bracket and parenthesis suffixes before we iterate
6041 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006042 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006043 return true;
6044 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006045 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006046 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006047 }
6048 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006049 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6050 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006051 return Error(Loc, "unexpected token in argument list");
6052 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006053 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006054 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006055}
6056
Nirav Dave996fc132016-05-05 14:15:46 +00006057// FIXME: Given that these have the same name, these should both be
6058// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006059bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006060 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006061 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006062}
6063
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006064bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006065 return Error(Loc, ErrorMsg);
6066}
6067
Jack Carter0b744b32012-10-04 02:29:46 +00006068bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006069 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006070 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006071
6072 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006073 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006074
6075 Parser.Lex(); // Eat "noat".
6076
Jack Carterd0bd6422013-04-18 00:41:53 +00006077 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006078 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006079 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006080 return false;
6081 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006082
6083 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006084 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006085 return false;
6086}
Jack Carterd0bd6422013-04-18 00:41:53 +00006087
Jack Carter0b744b32012-10-04 02:29:46 +00006088bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006089 // Line can be: ".set at", which sets $at to $1
6090 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006091 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006092 Parser.Lex(); // Eat "at".
6093
Jack Carter0b744b32012-10-04 02:29:46 +00006094 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006095 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006096 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006097
6098 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006099 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006100 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006101 }
6102
6103 if (getLexer().isNot(AsmToken::Equal)) {
6104 reportParseError("unexpected token, expected equals sign");
6105 return false;
6106 }
6107 Parser.Lex(); // Eat "=".
6108
6109 if (getLexer().isNot(AsmToken::Dollar)) {
6110 if (getLexer().is(AsmToken::EndOfStatement)) {
6111 reportParseError("no register specified");
6112 return false;
6113 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006114 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006115 return false;
6116 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006117 }
6118 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006119
Toma Tabacu16a74492015-02-13 10:30:57 +00006120 // Find out what "reg" is.
6121 unsigned AtRegNo;
6122 const AsmToken &Reg = Parser.getTok();
6123 if (Reg.is(AsmToken::Identifier)) {
6124 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6125 } else if (Reg.is(AsmToken::Integer)) {
6126 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006127 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006128 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006129 return false;
6130 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006131
6132 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006133 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006134 reportParseError("invalid register");
6135 return false;
6136 }
6137 Parser.Lex(); // Eat "reg".
6138
6139 // If this is not the end of the statement, report an error.
6140 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6141 reportParseError("unexpected token, expected end of statement");
6142 return false;
6143 }
6144
6145 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6146
6147 Parser.Lex(); // Consume the EndOfStatement.
6148 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006149}
6150
6151bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006152 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006153 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006154 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006155 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006156 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006157 return false;
6158 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006159 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006160 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006161 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006162 return false;
6163}
6164
6165bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006166 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006167 Parser.Lex();
6168 // If this is not the end of the statement, report an error.
6169 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006170 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006171 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006172 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006173 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006174 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006175 Parser.Lex(); // Consume the EndOfStatement.
6176 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006177}
6178
6179bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006180 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006181 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006182 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006183 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006184 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006185 return false;
6186 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006187 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006188 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006189 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006190 return false;
6191}
6192
6193bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006194 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006195 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006196 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006197 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006198 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006199 return false;
6200 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006201 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006202 reportParseError("`noreorder' must be set before `nomacro'");
6203 return false;
6204 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006205 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006206 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006207 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006208 return false;
6209}
Jack Carterd76b2372013-03-21 21:44:16 +00006210
Daniel Sanders44934432014-08-07 12:03:36 +00006211bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006212 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006213 Parser.Lex();
6214
6215 // If this is not the end of the statement, report an error.
6216 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006217 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006218
6219 setFeatureBits(Mips::FeatureMSA, "msa");
6220 getTargetStreamer().emitDirectiveSetMsa();
6221 return false;
6222}
6223
6224bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006225 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006226 Parser.Lex();
6227
6228 // If this is not the end of the statement, report an error.
6229 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006230 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006231
6232 clearFeatureBits(Mips::FeatureMSA, "msa");
6233 getTargetStreamer().emitDirectiveSetNoMsa();
6234 return false;
6235}
6236
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006237bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006238 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006239 Parser.Lex(); // Eat "nodsp".
6240
6241 // If this is not the end of the statement, report an error.
6242 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6243 reportParseError("unexpected token, expected end of statement");
6244 return false;
6245 }
6246
6247 clearFeatureBits(Mips::FeatureDSP, "dsp");
6248 getTargetStreamer().emitDirectiveSetNoDsp();
6249 return false;
6250}
6251
Toma Tabacucc2502d2014-11-04 17:18:07 +00006252bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006253 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006254 Parser.Lex(); // Eat "mips16".
6255
Jack Carter39536722014-01-22 23:08:42 +00006256 // If this is not the end of the statement, report an error.
6257 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006258 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006259 return false;
6260 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006261
6262 setFeatureBits(Mips::FeatureMips16, "mips16");
6263 getTargetStreamer().emitDirectiveSetMips16();
6264 Parser.Lex(); // Consume the EndOfStatement.
6265 return false;
6266}
6267
6268bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006269 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006270 Parser.Lex(); // Eat "nomips16".
6271
6272 // If this is not the end of the statement, report an error.
6273 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6274 reportParseError("unexpected token, expected end of statement");
6275 return false;
6276 }
6277
6278 clearFeatureBits(Mips::FeatureMips16, "mips16");
6279 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006280 Parser.Lex(); // Consume the EndOfStatement.
6281 return false;
6282}
6283
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006284bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006285 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006286 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006287 // Line can be: .set fp=32
6288 // .set fp=xx
6289 // .set fp=64
6290 Parser.Lex(); // Eat fp token
6291 AsmToken Tok = Parser.getTok();
6292 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006293 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006294 return false;
6295 }
6296 Parser.Lex(); // Eat '=' token.
6297 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006298
6299 if (!parseFpABIValue(FpAbiVal, ".set"))
6300 return false;
6301
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006302 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006303 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006304 return false;
6305 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006306 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006307 Parser.Lex(); // Consume the EndOfStatement.
6308 return false;
6309}
6310
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006311bool MipsAsmParser::parseSetOddSPRegDirective() {
6312 MCAsmParser &Parser = getParser();
6313
6314 Parser.Lex(); // Eat "oddspreg".
6315 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6316 reportParseError("unexpected token, expected end of statement");
6317 return false;
6318 }
6319
6320 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6321 getTargetStreamer().emitDirectiveSetOddSPReg();
6322 return false;
6323}
6324
6325bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6326 MCAsmParser &Parser = getParser();
6327
6328 Parser.Lex(); // Eat "nooddspreg".
6329 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6330 reportParseError("unexpected token, expected end of statement");
6331 return false;
6332 }
6333
6334 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6335 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6336 return false;
6337}
6338
Simon Dardis805f1e02017-07-11 21:28:36 +00006339bool MipsAsmParser::parseSetMtDirective() {
6340 MCAsmParser &Parser = getParser();
6341 Parser.Lex(); // Eat "mt".
6342
6343 // If this is not the end of the statement, report an error.
6344 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6345 reportParseError("unexpected token, expected end of statement");
6346 return false;
6347 }
6348
6349 setFeatureBits(Mips::FeatureMT, "mt");
6350 getTargetStreamer().emitDirectiveSetMt();
6351 Parser.Lex(); // Consume the EndOfStatement.
6352 return false;
6353}
6354
6355bool MipsAsmParser::parseSetNoMtDirective() {
6356 MCAsmParser &Parser = getParser();
6357 Parser.Lex(); // Eat "nomt".
6358
6359 // If this is not the end of the statement, report an error.
6360 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6361 reportParseError("unexpected token, expected end of statement");
6362 return false;
6363 }
6364
6365 clearFeatureBits(Mips::FeatureMT, "mt");
6366
6367 getTargetStreamer().emitDirectiveSetNoMt();
6368 Parser.Lex(); // Consume the EndOfStatement.
6369 return false;
6370}
6371
Toma Tabacu9db22db2014-09-09 10:15:38 +00006372bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006373 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006374 SMLoc Loc = getLexer().getLoc();
6375
6376 Parser.Lex();
6377 if (getLexer().isNot(AsmToken::EndOfStatement))
6378 return reportParseError("unexpected token, expected end of statement");
6379
6380 // Always keep an element on the options "stack" to prevent the user
6381 // from changing the initial options. This is how we remember them.
6382 if (AssemblerOptions.size() == 2)
6383 return reportParseError(Loc, ".set pop with no .set push");
6384
Akira Hatanakab11ef082015-11-14 06:35:56 +00006385 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006386 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006387 setAvailableFeatures(
6388 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6389 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006390
6391 getTargetStreamer().emitDirectiveSetPop();
6392 return false;
6393}
6394
6395bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006396 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006397 Parser.Lex();
6398 if (getLexer().isNot(AsmToken::EndOfStatement))
6399 return reportParseError("unexpected token, expected end of statement");
6400
6401 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006402 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006403 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006404
6405 getTargetStreamer().emitDirectiveSetPush();
6406 return false;
6407}
6408
Toma Tabacu29696502015-06-02 09:48:04 +00006409bool MipsAsmParser::parseSetSoftFloatDirective() {
6410 MCAsmParser &Parser = getParser();
6411 Parser.Lex();
6412 if (getLexer().isNot(AsmToken::EndOfStatement))
6413 return reportParseError("unexpected token, expected end of statement");
6414
6415 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6416 getTargetStreamer().emitDirectiveSetSoftFloat();
6417 return false;
6418}
6419
6420bool MipsAsmParser::parseSetHardFloatDirective() {
6421 MCAsmParser &Parser = getParser();
6422 Parser.Lex();
6423 if (getLexer().isNot(AsmToken::EndOfStatement))
6424 return reportParseError("unexpected token, expected end of statement");
6425
6426 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6427 getTargetStreamer().emitDirectiveSetHardFloat();
6428 return false;
6429}
6430
Jack Carterd76b2372013-03-21 21:44:16 +00006431bool MipsAsmParser::parseSetAssignment() {
6432 StringRef Name;
6433 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006434 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006435
6436 if (Parser.parseIdentifier(Name))
6437 reportParseError("expected identifier after .set");
6438
6439 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006440 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006441 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006442
Jack Carter3b2c96e2014-01-22 23:31:38 +00006443 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00006444 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00006445
Jim Grosbach6f482002015-05-18 18:43:14 +00006446 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00006447 Sym->setVariableValue(Value);
6448
6449 return false;
6450}
Jack Carterd0bd6422013-04-18 00:41:53 +00006451
Toma Tabacu26647792014-09-09 12:52:14 +00006452bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006453 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006454 Parser.Lex();
6455 if (getLexer().isNot(AsmToken::EndOfStatement))
6456 return reportParseError("unexpected token, expected end of statement");
6457
6458 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006459 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006460 setAvailableFeatures(
6461 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6462 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006463 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6464
6465 getTargetStreamer().emitDirectiveSetMips0();
6466 return false;
6467}
6468
Toma Tabacu85618b32014-08-19 14:22:52 +00006469bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006470 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006471 Parser.Lex();
6472 if (getLexer().isNot(AsmToken::Equal))
6473 return reportParseError("unexpected token, expected equals sign");
6474
6475 Parser.Lex();
6476 StringRef Arch;
6477 if (Parser.parseIdentifier(Arch))
6478 return reportParseError("expected arch identifier");
6479
6480 StringRef ArchFeatureName =
6481 StringSwitch<StringRef>(Arch)
6482 .Case("mips1", "mips1")
6483 .Case("mips2", "mips2")
6484 .Case("mips3", "mips3")
6485 .Case("mips4", "mips4")
6486 .Case("mips5", "mips5")
6487 .Case("mips32", "mips32")
6488 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006489 .Case("mips32r3", "mips32r3")
6490 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006491 .Case("mips32r6", "mips32r6")
6492 .Case("mips64", "mips64")
6493 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006494 .Case("mips64r3", "mips64r3")
6495 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006496 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006497 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006498 .Case("r4000", "mips3") // This is an implementation of Mips3.
6499 .Default("");
6500
6501 if (ArchFeatureName.empty())
6502 return reportParseError("unsupported architecture");
6503
6504 selectArch(ArchFeatureName);
6505 getTargetStreamer().emitDirectiveSetArch(Arch);
6506 return false;
6507}
6508
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006509bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006510 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006511 Parser.Lex();
6512 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006513 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006514
Matheus Almeida2852af82014-04-22 10:15:54 +00006515 switch (Feature) {
6516 default:
6517 llvm_unreachable("Unimplemented feature");
6518 case Mips::FeatureDSP:
6519 setFeatureBits(Mips::FeatureDSP, "dsp");
6520 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006521 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006522 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006523 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006524 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006525 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006526 case Mips::FeatureMips1:
6527 selectArch("mips1");
6528 getTargetStreamer().emitDirectiveSetMips1();
6529 break;
6530 case Mips::FeatureMips2:
6531 selectArch("mips2");
6532 getTargetStreamer().emitDirectiveSetMips2();
6533 break;
6534 case Mips::FeatureMips3:
6535 selectArch("mips3");
6536 getTargetStreamer().emitDirectiveSetMips3();
6537 break;
6538 case Mips::FeatureMips4:
6539 selectArch("mips4");
6540 getTargetStreamer().emitDirectiveSetMips4();
6541 break;
6542 case Mips::FeatureMips5:
6543 selectArch("mips5");
6544 getTargetStreamer().emitDirectiveSetMips5();
6545 break;
6546 case Mips::FeatureMips32:
6547 selectArch("mips32");
6548 getTargetStreamer().emitDirectiveSetMips32();
6549 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006550 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006551 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006552 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006553 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006554 case Mips::FeatureMips32r3:
6555 selectArch("mips32r3");
6556 getTargetStreamer().emitDirectiveSetMips32R3();
6557 break;
6558 case Mips::FeatureMips32r5:
6559 selectArch("mips32r5");
6560 getTargetStreamer().emitDirectiveSetMips32R5();
6561 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006562 case Mips::FeatureMips32r6:
6563 selectArch("mips32r6");
6564 getTargetStreamer().emitDirectiveSetMips32R6();
6565 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006566 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006567 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006568 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006569 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006570 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006571 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006572 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006573 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006574 case Mips::FeatureMips64r3:
6575 selectArch("mips64r3");
6576 getTargetStreamer().emitDirectiveSetMips64R3();
6577 break;
6578 case Mips::FeatureMips64r5:
6579 selectArch("mips64r5");
6580 getTargetStreamer().emitDirectiveSetMips64R5();
6581 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006582 case Mips::FeatureMips64r6:
6583 selectArch("mips64r6");
6584 getTargetStreamer().emitDirectiveSetMips64R6();
6585 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006586 }
6587 return false;
6588}
6589
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006590bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006591 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006592 if (getLexer().isNot(AsmToken::Comma)) {
6593 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006594 return Error(Loc, ErrorStr);
6595 }
6596
Matheus Almeida2852af82014-04-22 10:15:54 +00006597 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006598 return true;
6599}
6600
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006601// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
6602// In this class, it is only used for .cprestore.
6603// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
6604// MipsTargetELFStreamer and MipsAsmParser.
6605bool MipsAsmParser::isPicAndNotNxxAbi() {
6606 return inPicMode() && !(isABI_N32() || isABI_N64());
6607}
6608
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006609bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00006610 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00006611 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006612
Toma Tabacudde4c462014-11-06 10:02:45 +00006613 if (inMips16Mode()) {
6614 reportParseError(".cpload is not supported in Mips16 mode");
6615 return false;
6616 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006617
David Blaikie960ea3f2014-06-08 16:18:35 +00006618 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00006619 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006620 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6621 reportParseError("expected register containing function address");
6622 return false;
6623 }
6624
David Blaikie960ea3f2014-06-08 16:18:35 +00006625 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
6626 if (!RegOpnd.isGPRAsmReg()) {
6627 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006628 return false;
6629 }
6630
Toma Tabacudde4c462014-11-06 10:02:45 +00006631 // If this is not the end of the statement, report an error.
6632 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6633 reportParseError("unexpected token, expected end of statement");
6634 return false;
6635 }
6636
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006637 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006638 return false;
6639}
6640
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006641bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
6642 MCAsmParser &Parser = getParser();
6643
6644 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
6645 // is used in non-PIC mode.
6646
6647 if (inMips16Mode()) {
6648 reportParseError(".cprestore is not supported in Mips16 mode");
6649 return false;
6650 }
6651
6652 // Get the stack offset value.
6653 const MCExpr *StackOffset;
6654 int64_t StackOffsetVal;
6655 if (Parser.parseExpression(StackOffset)) {
6656 reportParseError("expected stack offset value");
6657 return false;
6658 }
6659
6660 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
6661 reportParseError("stack offset is not an absolute expression");
6662 return false;
6663 }
6664
6665 if (StackOffsetVal < 0) {
6666 Warning(Loc, ".cprestore with negative stack offset has no effect");
6667 IsCpRestoreSet = false;
6668 } else {
6669 IsCpRestoreSet = true;
6670 CpRestoreOffset = StackOffsetVal;
6671 }
6672
6673 // If this is not the end of the statement, report an error.
6674 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6675 reportParseError("unexpected token, expected end of statement");
6676 return false;
6677 }
6678
Daniel Sandersdf8510d2016-05-11 12:48:19 +00006679 if (!getTargetStreamer().emitDirectiveCpRestore(
6680 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00006681 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006682 Parser.Lex(); // Consume the EndOfStatement.
6683 return false;
6684}
6685
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006686bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006687 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006688 unsigned FuncReg;
6689 unsigned Save;
6690 bool SaveIsReg = true;
6691
Matheus Almeida7e815762014-06-18 13:08:59 +00006692 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006693 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006694 if (ResTy == MatchOperand_NoMatch) {
6695 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00006696 return false;
6697 }
6698
6699 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6700 if (!FuncRegOpnd.isGPRAsmReg()) {
6701 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006702 return false;
6703 }
6704
6705 FuncReg = FuncRegOpnd.getGPR32Reg();
6706 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006707
Toma Tabacu65f10572014-09-16 15:00:52 +00006708 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006709 return true;
6710
Toma Tabacu13964452014-09-04 13:23:44 +00006711 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006712 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00006713 const MCExpr *OffsetExpr;
6714 int64_t OffsetVal;
6715 SMLoc ExprLoc = getLexer().getLoc();
6716
6717 if (Parser.parseExpression(OffsetExpr) ||
6718 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
6719 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00006720 return false;
6721 }
Daniel Sanders5d796282015-09-21 09:26:55 +00006722
6723 Save = OffsetVal;
6724 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00006725 } else {
6726 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6727 if (!SaveOpnd.isGPRAsmReg()) {
6728 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006729 return false;
6730 }
6731 Save = SaveOpnd.getGPR32Reg();
6732 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006733
Toma Tabacu65f10572014-09-16 15:00:52 +00006734 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006735 return true;
6736
Toma Tabacu8874eac2015-02-18 13:46:53 +00006737 const MCExpr *Expr;
6738 if (Parser.parseExpression(Expr)) {
6739 reportParseError("expected expression");
6740 return false;
6741 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006742
Toma Tabacu8874eac2015-02-18 13:46:53 +00006743 if (Expr->getKind() != MCExpr::SymbolRef) {
6744 reportParseError("expected symbol");
6745 return false;
6746 }
6747 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
6748
Daniel Sandersf173dda2015-09-22 10:50:09 +00006749 CpSaveLocation = Save;
6750 CpSaveLocationIsRegister = SaveIsReg;
6751
Toma Tabacu8874eac2015-02-18 13:46:53 +00006752 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
6753 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006754 return false;
6755}
6756
Daniel Sandersf173dda2015-09-22 10:50:09 +00006757bool MipsAsmParser::parseDirectiveCPReturn() {
6758 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
6759 CpSaveLocationIsRegister);
6760 return false;
6761}
6762
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006763bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006764 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006765 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6766 const AsmToken &Tok = Parser.getTok();
6767
6768 if (Tok.getString() == "2008") {
6769 Parser.Lex();
6770 getTargetStreamer().emitDirectiveNaN2008();
6771 return false;
6772 } else if (Tok.getString() == "legacy") {
6773 Parser.Lex();
6774 getTargetStreamer().emitDirectiveNaNLegacy();
6775 return false;
6776 }
6777 }
6778 // If we don't recognize the option passed to the .nan
6779 // directive (e.g. no option or unknown option), emit an error.
6780 reportParseError("invalid option in .nan directive");
6781 return false;
6782}
6783
Jack Carter0b744b32012-10-04 02:29:46 +00006784bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006785 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006786 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00006787 const AsmToken &Tok = Parser.getTok();
6788
6789 if (Tok.getString() == "noat") {
6790 return parseSetNoAtDirective();
6791 } else if (Tok.getString() == "at") {
6792 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00006793 } else if (Tok.getString() == "arch") {
6794 return parseSetArchDirective();
Simon Dardisac9c30c2017-02-01 18:50:24 +00006795 } else if (Tok.getString() == "bopt") {
6796 Warning(Tok.getLoc(), "'bopt' feature is unsupported");
6797 getParser().Lex();
6798 return false;
6799 } else if (Tok.getString() == "nobopt") {
6800 // We're already running in nobopt mode, so nothing to do.
6801 getParser().Lex();
6802 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006803 } else if (Tok.getString() == "fp") {
6804 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006805 } else if (Tok.getString() == "oddspreg") {
6806 return parseSetOddSPRegDirective();
6807 } else if (Tok.getString() == "nooddspreg") {
6808 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006809 } else if (Tok.getString() == "pop") {
6810 return parseSetPopDirective();
6811 } else if (Tok.getString() == "push") {
6812 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00006813 } else if (Tok.getString() == "reorder") {
6814 return parseSetReorderDirective();
6815 } else if (Tok.getString() == "noreorder") {
6816 return parseSetNoReorderDirective();
6817 } else if (Tok.getString() == "macro") {
6818 return parseSetMacroDirective();
6819 } else if (Tok.getString() == "nomacro") {
6820 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00006821 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00006822 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006823 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00006824 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006825 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00006826 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00006827 getTargetStreamer().emitDirectiveSetNoMicroMips();
6828 Parser.eatToEndOfStatement();
6829 return false;
6830 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006831 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00006832 } else if (Tok.getString() == "mips0") {
6833 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00006834 } else if (Tok.getString() == "mips1") {
6835 return parseSetFeature(Mips::FeatureMips1);
6836 } else if (Tok.getString() == "mips2") {
6837 return parseSetFeature(Mips::FeatureMips2);
6838 } else if (Tok.getString() == "mips3") {
6839 return parseSetFeature(Mips::FeatureMips3);
6840 } else if (Tok.getString() == "mips4") {
6841 return parseSetFeature(Mips::FeatureMips4);
6842 } else if (Tok.getString() == "mips5") {
6843 return parseSetFeature(Mips::FeatureMips5);
6844 } else if (Tok.getString() == "mips32") {
6845 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00006846 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006847 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006848 } else if (Tok.getString() == "mips32r3") {
6849 return parseSetFeature(Mips::FeatureMips32r3);
6850 } else if (Tok.getString() == "mips32r5") {
6851 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006852 } else if (Tok.getString() == "mips32r6") {
6853 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006854 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006855 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006856 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006857 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006858 } else if (Tok.getString() == "mips64r3") {
6859 return parseSetFeature(Mips::FeatureMips64r3);
6860 } else if (Tok.getString() == "mips64r5") {
6861 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006862 } else if (Tok.getString() == "mips64r6") {
6863 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00006864 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006865 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006866 } else if (Tok.getString() == "nodsp") {
6867 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00006868 } else if (Tok.getString() == "msa") {
6869 return parseSetMsaDirective();
6870 } else if (Tok.getString() == "nomsa") {
6871 return parseSetNoMsaDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +00006872 } else if (Tok.getString() == "mt") {
6873 return parseSetMtDirective();
6874 } else if (Tok.getString() == "nomt") {
6875 return parseSetNoMtDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00006876 } else if (Tok.getString() == "softfloat") {
6877 return parseSetSoftFloatDirective();
6878 } else if (Tok.getString() == "hardfloat") {
6879 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00006880 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00006881 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00006882 parseSetAssignment();
6883 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006884 }
Jack Carter07c818d2013-01-25 01:31:34 +00006885
Jack Carter0b744b32012-10-04 02:29:46 +00006886 return true;
6887}
6888
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006889/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00006890/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006891bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006892 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006893 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006894 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00006895 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00006896 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00006897 return true;
6898
6899 getParser().getStreamer().EmitValue(Value, Size);
6900
6901 if (getLexer().is(AsmToken::EndOfStatement))
6902 break;
6903
Jack Carter07c818d2013-01-25 01:31:34 +00006904 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006905 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00006906 Parser.Lex();
6907 }
6908 }
6909
6910 Parser.Lex();
6911 return false;
6912}
6913
Vladimir Medic4c299852013-11-06 11:27:05 +00006914/// parseDirectiveGpWord
6915/// ::= .gpword local_sym
6916bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006917 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00006918 const MCExpr *Value;
6919 // EmitGPRel32Value requires an expression, so we are using base class
6920 // method to evaluate the expression.
6921 if (getParser().parseExpression(Value))
6922 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00006923 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00006924
Vladimir Medice10c1122013-11-13 13:18:04 +00006925 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006926 return Error(getLexer().getLoc(),
6927 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00006928 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00006929 return false;
6930}
6931
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006932/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00006933/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006934bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006935 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006936 const MCExpr *Value;
6937 // EmitGPRel64Value requires an expression, so we are using base class
6938 // method to evaluate the expression.
6939 if (getParser().parseExpression(Value))
6940 return true;
6941 getParser().getStreamer().EmitGPRel64Value(Value);
6942
6943 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006944 return Error(getLexer().getLoc(),
6945 "unexpected token, expected end of statement");
6946 Parser.Lex(); // Eat EndOfStatement token.
6947 return false;
6948}
6949
6950/// parseDirectiveDtpRelWord
6951/// ::= .dtprelword tls_sym
6952bool MipsAsmParser::parseDirectiveDtpRelWord() {
6953 MCAsmParser &Parser = getParser();
6954 const MCExpr *Value;
6955 // EmitDTPRel32Value requires an expression, so we are using base class
6956 // method to evaluate the expression.
6957 if (getParser().parseExpression(Value))
6958 return true;
6959 getParser().getStreamer().EmitDTPRel32Value(Value);
6960
6961 if (getLexer().isNot(AsmToken::EndOfStatement))
6962 return Error(getLexer().getLoc(),
6963 "unexpected token, expected end of statement");
6964 Parser.Lex(); // Eat EndOfStatement token.
6965 return false;
6966}
6967
6968/// parseDirectiveDtpRelDWord
6969/// ::= .dtpreldword tls_sym
6970bool MipsAsmParser::parseDirectiveDtpRelDWord() {
6971 MCAsmParser &Parser = getParser();
6972 const MCExpr *Value;
6973 // EmitDTPRel64Value requires an expression, so we are using base class
6974 // method to evaluate the expression.
6975 if (getParser().parseExpression(Value))
6976 return true;
6977 getParser().getStreamer().EmitDTPRel64Value(Value);
6978
6979 if (getLexer().isNot(AsmToken::EndOfStatement))
6980 return Error(getLexer().getLoc(),
6981 "unexpected token, expected end of statement");
6982 Parser.Lex(); // Eat EndOfStatement token.
6983 return false;
6984}
6985
6986/// parseDirectiveTpRelWord
6987/// ::= .tprelword tls_sym
6988bool MipsAsmParser::parseDirectiveTpRelWord() {
6989 MCAsmParser &Parser = getParser();
6990 const MCExpr *Value;
6991 // EmitTPRel32Value requires an expression, so we are using base class
6992 // method to evaluate the expression.
6993 if (getParser().parseExpression(Value))
6994 return true;
6995 getParser().getStreamer().EmitTPRel32Value(Value);
6996
6997 if (getLexer().isNot(AsmToken::EndOfStatement))
6998 return Error(getLexer().getLoc(),
6999 "unexpected token, expected end of statement");
7000 Parser.Lex(); // Eat EndOfStatement token.
7001 return false;
7002}
7003
7004/// parseDirectiveTpRelDWord
7005/// ::= .tpreldword tls_sym
7006bool MipsAsmParser::parseDirectiveTpRelDWord() {
7007 MCAsmParser &Parser = getParser();
7008 const MCExpr *Value;
7009 // EmitTPRel64Value requires an expression, so we are using base class
7010 // method to evaluate the expression.
7011 if (getParser().parseExpression(Value))
7012 return true;
7013 getParser().getStreamer().EmitTPRel64Value(Value);
7014
7015 if (getLexer().isNot(AsmToken::EndOfStatement))
7016 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007017 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00007018 Parser.Lex(); // Eat EndOfStatement token.
7019 return false;
7020}
7021
Jack Carter0cd3c192014-01-06 23:27:31 +00007022bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007023 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00007024 // Get the option token.
7025 AsmToken Tok = Parser.getTok();
7026 // At the moment only identifiers are supported.
7027 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007028 return Error(Parser.getTok().getLoc(),
7029 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00007030 }
7031
7032 StringRef Option = Tok.getIdentifier();
7033
7034 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007035 // MipsAsmParser needs to know if the current PIC mode changes.
7036 IsPicEnabled = false;
7037
Jack Carter0cd3c192014-01-06 23:27:31 +00007038 getTargetStreamer().emitDirectiveOptionPic0();
7039 Parser.Lex();
7040 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007041 return Error(Parser.getTok().getLoc(),
7042 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007043 }
7044 return false;
7045 }
7046
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007047 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007048 // MipsAsmParser needs to know if the current PIC mode changes.
7049 IsPicEnabled = true;
7050
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007051 getTargetStreamer().emitDirectiveOptionPic2();
7052 Parser.Lex();
7053 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007054 return Error(Parser.getTok().getLoc(),
7055 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007056 }
7057 return false;
7058 }
7059
Jack Carter0cd3c192014-01-06 23:27:31 +00007060 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00007061 Warning(Parser.getTok().getLoc(),
7062 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007063 Parser.eatToEndOfStatement();
7064 return false;
7065}
7066
Toma Tabacu9ca50962015-04-16 09:53:47 +00007067/// parseInsnDirective
7068/// ::= .insn
7069bool MipsAsmParser::parseInsnDirective() {
7070 // If this is not the end of the statement, report an error.
7071 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7072 reportParseError("unexpected token, expected end of statement");
7073 return false;
7074 }
7075
7076 // The actual label marking happens in
7077 // MipsELFStreamer::createPendingLabelRelocs().
7078 getTargetStreamer().emitDirectiveInsn();
7079
7080 getParser().Lex(); // Eat EndOfStatement token.
7081 return false;
7082}
7083
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007084/// parseRSectionDirective
7085/// ::= .rdata
7086bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
7087 // If this is not the end of the statement, report an error.
7088 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7089 reportParseError("unexpected token, expected end of statement");
7090 return false;
7091 }
7092
7093 MCSection *ELFSection = getContext().getELFSection(
7094 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7095 getParser().getStreamer().SwitchSection(ELFSection);
7096
7097 getParser().Lex(); // Eat EndOfStatement token.
7098 return false;
7099}
7100
Simon Atanasyanbe186202016-02-11 06:45:54 +00007101/// parseSSectionDirective
7102/// ::= .sbss
7103/// ::= .sdata
7104bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7105 // If this is not the end of the statement, report an error.
7106 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7107 reportParseError("unexpected token, expected end of statement");
7108 return false;
7109 }
7110
7111 MCSection *ELFSection = getContext().getELFSection(
7112 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7113 getParser().getStreamer().SwitchSection(ELFSection);
7114
7115 getParser().Lex(); // Eat EndOfStatement token.
7116 return false;
7117}
7118
Daniel Sanders7e527422014-07-10 13:38:23 +00007119/// parseDirectiveModule
7120/// ::= .module oddspreg
7121/// ::= .module nooddspreg
7122/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007123/// ::= .module softfloat
7124/// ::= .module hardfloat
Simon Dardis805f1e02017-07-11 21:28:36 +00007125/// ::= .module mt
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007126bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007127 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007128 MCAsmLexer &Lexer = getLexer();
7129 SMLoc L = Lexer.getLoc();
7130
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007131 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007132 // TODO : get a better message.
7133 reportParseError(".module directive must appear before any code");
7134 return false;
7135 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007136
Toma Tabacuc405c822015-01-23 10:40:19 +00007137 StringRef Option;
7138 if (Parser.parseIdentifier(Option)) {
7139 reportParseError("expected .module option identifier");
7140 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007141 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007142
Toma Tabacuc405c822015-01-23 10:40:19 +00007143 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007144 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007145
Toma Tabacu3c499582015-06-25 10:56:57 +00007146 // Synchronize the abiflags information with the FeatureBits information we
7147 // changed above.
7148 getTargetStreamer().updateABIInfo(*this);
7149
7150 // If printing assembly, use the recently updated abiflags information.
7151 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7152 // emitted at the end).
7153 getTargetStreamer().emitDirectiveModuleOddSPReg();
7154
Toma Tabacuc405c822015-01-23 10:40:19 +00007155 // If this is not the end of the statement, report an error.
7156 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7157 reportParseError("unexpected token, expected end of statement");
7158 return false;
7159 }
7160
7161 return false; // parseDirectiveModule has finished successfully.
7162 } else if (Option == "nooddspreg") {
7163 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007164 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007165 }
7166
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007167 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007168
Toma Tabacu3c499582015-06-25 10:56:57 +00007169 // Synchronize the abiflags information with the FeatureBits information we
7170 // changed above.
7171 getTargetStreamer().updateABIInfo(*this);
7172
7173 // If printing assembly, use the recently updated abiflags information.
7174 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7175 // emitted at the end).
7176 getTargetStreamer().emitDirectiveModuleOddSPReg();
7177
Toma Tabacuc405c822015-01-23 10:40:19 +00007178 // If this is not the end of the statement, report an error.
7179 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7180 reportParseError("unexpected token, expected end of statement");
7181 return false;
7182 }
7183
7184 return false; // parseDirectiveModule has finished successfully.
7185 } else if (Option == "fp") {
7186 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007187 } else if (Option == "softfloat") {
7188 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7189
7190 // Synchronize the ABI Flags information with the FeatureBits information we
7191 // updated above.
7192 getTargetStreamer().updateABIInfo(*this);
7193
7194 // If printing assembly, use the recently updated ABI Flags information.
7195 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7196 // emitted later).
7197 getTargetStreamer().emitDirectiveModuleSoftFloat();
7198
7199 // If this is not the end of the statement, report an error.
7200 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7201 reportParseError("unexpected token, expected end of statement");
7202 return false;
7203 }
7204
7205 return false; // parseDirectiveModule has finished successfully.
7206 } else if (Option == "hardfloat") {
7207 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7208
7209 // Synchronize the ABI Flags information with the FeatureBits information we
7210 // updated above.
7211 getTargetStreamer().updateABIInfo(*this);
7212
7213 // If printing assembly, use the recently updated ABI Flags information.
7214 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7215 // emitted later).
7216 getTargetStreamer().emitDirectiveModuleHardFloat();
7217
7218 // If this is not the end of the statement, report an error.
7219 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7220 reportParseError("unexpected token, expected end of statement");
7221 return false;
7222 }
7223
7224 return false; // parseDirectiveModule has finished successfully.
Simon Dardis805f1e02017-07-11 21:28:36 +00007225 } else if (Option == "mt") {
7226 setModuleFeatureBits(Mips::FeatureMT, "mt");
7227
7228 // Synchronize the ABI Flags information with the FeatureBits information we
7229 // updated above.
7230 getTargetStreamer().updateABIInfo(*this);
7231
Simon Dardisd9611922017-07-11 21:36:58 +00007232 // If printing assembly, use the recently updated ABI Flags information.
Simon Dardis805f1e02017-07-11 21:28:36 +00007233 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7234 // emitted later).
7235 getTargetStreamer().emitDirectiveModuleMT();
7236
7237 // If this is not the end of the statement, report an error.
7238 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7239 reportParseError("unexpected token, expected end of statement");
7240 return false;
7241 }
7242
7243 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007244 } else {
7245 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7246 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007247}
7248
7249/// parseDirectiveModuleFP
7250/// ::= =32
7251/// ::= =xx
7252/// ::= =64
7253bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007254 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007255 MCAsmLexer &Lexer = getLexer();
7256
7257 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007258 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007259 return false;
7260 }
7261 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007262
Daniel Sanders7e527422014-07-10 13:38:23 +00007263 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007264 if (!parseFpABIValue(FpABI, ".module"))
7265 return false;
7266
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007267 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007268 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007269 return false;
7270 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007271
Toma Tabacua64e5402015-06-25 12:44:38 +00007272 // Synchronize the abiflags information with the FeatureBits information we
7273 // changed above.
7274 getTargetStreamer().updateABIInfo(*this);
7275
7276 // If printing assembly, use the recently updated abiflags information.
7277 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7278 // emitted at the end).
7279 getTargetStreamer().emitDirectiveModuleFP();
7280
Daniel Sanders7e527422014-07-10 13:38:23 +00007281 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007282 return false;
7283}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007284
Daniel Sanders7e527422014-07-10 13:38:23 +00007285bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007286 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007287 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007288 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007289 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007290
7291 if (Lexer.is(AsmToken::Identifier)) {
7292 StringRef Value = Parser.getTok().getString();
7293 Parser.Lex();
7294
7295 if (Value != "xx") {
7296 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7297 return false;
7298 }
7299
7300 if (!isABI_O32()) {
7301 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7302 return false;
7303 }
7304
Daniel Sanders7e527422014-07-10 13:38:23 +00007305 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007306 if (ModuleLevelOptions) {
7307 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7308 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7309 } else {
7310 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7311 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7312 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007313 return true;
7314 }
7315
7316 if (Lexer.is(AsmToken::Integer)) {
7317 unsigned Value = Parser.getTok().getIntVal();
7318 Parser.Lex();
7319
7320 if (Value != 32 && Value != 64) {
7321 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7322 return false;
7323 }
7324
7325 if (Value == 32) {
7326 if (!isABI_O32()) {
7327 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7328 return false;
7329 }
7330
Daniel Sanders7e527422014-07-10 13:38:23 +00007331 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007332 if (ModuleLevelOptions) {
7333 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7334 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7335 } else {
7336 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7337 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7338 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007339 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007340 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007341 if (ModuleLevelOptions) {
7342 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7343 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7344 } else {
7345 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7346 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7347 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007348 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007349
Daniel Sanders7e527422014-07-10 13:38:23 +00007350 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007351 }
7352
7353 return false;
7354}
7355
Jack Carter0b744b32012-10-04 02:29:46 +00007356bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007357 // This returns false if this function recognizes the directive
7358 // regardless of whether it is successfully handles or reports an
7359 // error. Otherwise it returns true to give the generic parser a
7360 // chance at recognizing it.
7361
Rafael Espindola961d4692014-11-11 05:18:41 +00007362 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007363 StringRef IDVal = DirectiveID.getString();
7364
Nirav Dave996fc132016-05-05 14:15:46 +00007365 if (IDVal == ".cpload") {
7366 parseDirectiveCpLoad(DirectiveID.getLoc());
7367 return false;
7368 }
7369 if (IDVal == ".cprestore") {
7370 parseDirectiveCpRestore(DirectiveID.getLoc());
7371 return false;
7372 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00007373 if (IDVal == ".dword") {
7374 parseDataDirective(8, DirectiveID.getLoc());
7375 return false;
7376 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007377 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007378 StringRef SymbolName;
7379
7380 if (Parser.parseIdentifier(SymbolName)) {
7381 reportParseError("expected identifier after .ent");
7382 return false;
7383 }
7384
7385 // There's an undocumented extension that allows an integer to
7386 // follow the name of the procedure which AFAICS is ignored by GAS.
7387 // Example: .ent foo,2
7388 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7389 if (getLexer().isNot(AsmToken::Comma)) {
7390 // Even though we accept this undocumented extension for compatibility
7391 // reasons, the additional integer argument does not actually change
7392 // the behaviour of the '.ent' directive, so we would like to discourage
7393 // its use. We do this by not referring to the extended version in
7394 // error messages which are not directly related to its use.
7395 reportParseError("unexpected token, expected end of statement");
7396 return false;
7397 }
7398 Parser.Lex(); // Eat the comma.
7399 const MCExpr *DummyNumber;
7400 int64_t DummyNumberVal;
7401 // If the user was explicitly trying to use the extended version,
7402 // we still give helpful extension-related error messages.
7403 if (Parser.parseExpression(DummyNumber)) {
7404 reportParseError("expected number after comma");
7405 return false;
7406 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007407 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007408 reportParseError("expected an absolute expression after comma");
7409 return false;
7410 }
7411 }
7412
7413 // If this is not the end of the statement, report an error.
7414 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7415 reportParseError("unexpected token, expected end of statement");
7416 return false;
7417 }
7418
Jim Grosbach6f482002015-05-18 18:43:14 +00007419 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007420
7421 getTargetStreamer().emitDirectiveEnt(*Sym);
7422 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007423 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007424 return false;
7425 }
7426
Jack Carter07c818d2013-01-25 01:31:34 +00007427 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007428 StringRef SymbolName;
7429
7430 if (Parser.parseIdentifier(SymbolName)) {
7431 reportParseError("expected identifier after .end");
7432 return false;
7433 }
7434
7435 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7436 reportParseError("unexpected token, expected end of statement");
7437 return false;
7438 }
7439
7440 if (CurrentFn == nullptr) {
7441 reportParseError(".end used without .ent");
7442 return false;
7443 }
7444
7445 if ((SymbolName != CurrentFn->getName())) {
7446 reportParseError(".end symbol does not match .ent symbol");
7447 return false;
7448 }
7449
7450 getTargetStreamer().emitDirectiveEnd(SymbolName);
7451 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007452 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007453 return false;
7454 }
7455
Jack Carter07c818d2013-01-25 01:31:34 +00007456 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007457 // .frame $stack_reg, frame_size_in_bytes, $return_reg
7458 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007459 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007460 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7461 reportParseError("expected stack register");
7462 return false;
7463 }
7464
7465 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7466 if (!StackRegOpnd.isGPRAsmReg()) {
7467 reportParseError(StackRegOpnd.getStartLoc(),
7468 "expected general purpose register");
7469 return false;
7470 }
7471 unsigned StackReg = StackRegOpnd.getGPR32Reg();
7472
7473 if (Parser.getTok().is(AsmToken::Comma))
7474 Parser.Lex();
7475 else {
7476 reportParseError("unexpected token, expected comma");
7477 return false;
7478 }
7479
7480 // Parse the frame size.
7481 const MCExpr *FrameSize;
7482 int64_t FrameSizeVal;
7483
7484 if (Parser.parseExpression(FrameSize)) {
7485 reportParseError("expected frame size value");
7486 return false;
7487 }
7488
Jim Grosbach13760bd2015-05-30 01:25:56 +00007489 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007490 reportParseError("frame size not an absolute expression");
7491 return false;
7492 }
7493
7494 if (Parser.getTok().is(AsmToken::Comma))
7495 Parser.Lex();
7496 else {
7497 reportParseError("unexpected token, expected comma");
7498 return false;
7499 }
7500
7501 // Parse the return register.
7502 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00007503 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007504 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7505 reportParseError("expected return register");
7506 return false;
7507 }
7508
7509 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7510 if (!ReturnRegOpnd.isGPRAsmReg()) {
7511 reportParseError(ReturnRegOpnd.getStartLoc(),
7512 "expected general purpose register");
7513 return false;
7514 }
7515
7516 // If this is not the end of the statement, report an error.
7517 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7518 reportParseError("unexpected token, expected end of statement");
7519 return false;
7520 }
7521
7522 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
7523 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007524 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007525 return false;
7526 }
7527
Jack Carter07c818d2013-01-25 01:31:34 +00007528 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00007529 parseDirectiveSet();
7530 return false;
Jack Carterbe332172012-09-07 00:48:02 +00007531 }
7532
Daniel Sandersd97a6342014-08-13 10:07:34 +00007533 if (IDVal == ".mask" || IDVal == ".fmask") {
7534 // .mask bitmask, frame_offset
7535 // bitmask: One bit for each register used.
7536 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
7537 // first register is expected to be saved.
7538 // Examples:
7539 // .mask 0x80000000, -4
7540 // .fmask 0x80000000, -4
7541 //
Jack Carterbe332172012-09-07 00:48:02 +00007542
Daniel Sandersd97a6342014-08-13 10:07:34 +00007543 // Parse the bitmask
7544 const MCExpr *BitMask;
7545 int64_t BitMaskVal;
7546
7547 if (Parser.parseExpression(BitMask)) {
7548 reportParseError("expected bitmask value");
7549 return false;
7550 }
7551
Jim Grosbach13760bd2015-05-30 01:25:56 +00007552 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007553 reportParseError("bitmask not an absolute expression");
7554 return false;
7555 }
7556
7557 if (Parser.getTok().is(AsmToken::Comma))
7558 Parser.Lex();
7559 else {
7560 reportParseError("unexpected token, expected comma");
7561 return false;
7562 }
7563
7564 // Parse the frame_offset
7565 const MCExpr *FrameOffset;
7566 int64_t FrameOffsetVal;
7567
7568 if (Parser.parseExpression(FrameOffset)) {
7569 reportParseError("expected frame offset value");
7570 return false;
7571 }
7572
Jim Grosbach13760bd2015-05-30 01:25:56 +00007573 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007574 reportParseError("frame offset not an absolute expression");
7575 return false;
7576 }
7577
7578 // If this is not the end of the statement, report an error.
7579 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7580 reportParseError("unexpected token, expected end of statement");
7581 return false;
7582 }
7583
7584 if (IDVal == ".mask")
7585 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
7586 else
7587 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00007588 return false;
7589 }
7590
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007591 if (IDVal == ".nan")
7592 return parseDirectiveNaN();
7593
Jack Carter07c818d2013-01-25 01:31:34 +00007594 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00007595 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00007596 return false;
7597 }
7598
Rafael Espindolab59fb732014-03-28 18:50:26 +00007599 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007600 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007601 return false;
7602 }
7603
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007604 if (IDVal == ".dtprelword") {
7605 parseDirectiveDtpRelWord();
7606 return false;
7607 }
7608
7609 if (IDVal == ".dtpreldword") {
7610 parseDirectiveDtpRelDWord();
7611 return false;
7612 }
7613
7614 if (IDVal == ".tprelword") {
7615 parseDirectiveTpRelWord();
7616 return false;
7617 }
7618
7619 if (IDVal == ".tpreldword") {
7620 parseDirectiveTpRelDWord();
7621 return false;
7622 }
7623
Jack Carter07c818d2013-01-25 01:31:34 +00007624 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007625 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00007626 return false;
7627 }
7628
Scott Egertond1aeb052016-02-15 16:11:51 +00007629 if (IDVal == ".hword") {
7630 parseDataDirective(2, DirectiveID.getLoc());
7631 return false;
7632 }
7633
Nirav Dave996fc132016-05-05 14:15:46 +00007634 if (IDVal == ".option") {
7635 parseDirectiveOption();
7636 return false;
7637 }
Jack Carter0cd3c192014-01-06 23:27:31 +00007638
7639 if (IDVal == ".abicalls") {
7640 getTargetStreamer().emitDirectiveAbiCalls();
7641 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007642 Error(Parser.getTok().getLoc(),
7643 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007644 }
7645 return false;
7646 }
7647
Nirav Dave996fc132016-05-05 14:15:46 +00007648 if (IDVal == ".cpsetup") {
7649 parseDirectiveCPSetup();
7650 return false;
7651 }
7652 if (IDVal == ".cpreturn") {
7653 parseDirectiveCPReturn();
7654 return false;
7655 }
7656 if (IDVal == ".module") {
7657 parseDirectiveModule();
7658 return false;
7659 }
7660 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
7661 parseInternalDirectiveReallowModule();
7662 return false;
7663 }
7664 if (IDVal == ".insn") {
7665 parseInsnDirective();
7666 return false;
7667 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007668 if (IDVal == ".rdata") {
7669 parseRSectionDirective(".rodata");
7670 return false;
7671 }
Nirav Dave996fc132016-05-05 14:15:46 +00007672 if (IDVal == ".sbss") {
7673 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
7674 return false;
7675 }
7676 if (IDVal == ".sdata") {
7677 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
7678 return false;
7679 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00007680
Rafael Espindola870c4e92012-01-11 03:56:41 +00007681 return true;
7682}
7683
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00007684bool MipsAsmParser::parseInternalDirectiveReallowModule() {
7685 // If this is not the end of the statement, report an error.
7686 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7687 reportParseError("unexpected token, expected end of statement");
7688 return false;
7689 }
7690
7691 getTargetStreamer().reallowModuleDirective();
7692
7693 getParser().Lex(); // Eat EndOfStatement token.
7694 return false;
7695}
7696
Rafael Espindola870c4e92012-01-11 03:56:41 +00007697extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00007698 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
7699 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
7700 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
7701 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00007702}
Jack Carterb4dbc172012-09-05 23:34:03 +00007703
7704#define GET_REGISTER_MATCHER
7705#define GET_MATCHER_IMPLEMENTATION
7706#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00007707
7708bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
7709 // Find the appropriate table for this asm variant.
7710 const MatchEntry *Start, *End;
7711 switch (VariantID) {
7712 default: llvm_unreachable("invalid variant!");
7713 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
7714 }
7715 // Search the table.
7716 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
7717 return MnemonicRange.first != MnemonicRange.second;
7718}