blob: 2a69860a0fedb054ede7d7f81f9d1a76ab24e93a [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"
Petar Jovanovica5da5882014-02-04 18:41:57 +000012#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000013#include "MCTargetDesc/MipsMCTargetDesc.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000014#include "MipsTargetStreamer.h"
Hrvoje Vargadbe4d962016-09-08 07:41:43 +000015#include "MCTargetDesc/MipsBaseInfo.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000017#include "llvm/ADT/STLExtras.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/ADT/StringSwitch.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000019#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/Triple.h"
21#include "llvm/ADT/Twine.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000022#include "llvm/MC/MCContext.h"
23#include "llvm/MC/MCExpr.h"
24#include "llvm/MC/MCInst.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000025#include "llvm/MC/MCInstrDesc.h"
26#include "llvm/MC/MCObjectFileInfo.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000027#include "llvm/MC/MCParser/MCAsmLexer.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000028#include "llvm/MC/MCParser/MCAsmParser.h"
29#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000030#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000031#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000032#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000033#include "llvm/MC/MCStreamer.h"
34#include "llvm/MC/MCSubtargetInfo.h"
35#include "llvm/MC/MCSymbol.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000036#include "llvm/MC/MCSymbolELF.h"
37#include "llvm/MC/MCValue.h"
38#include "llvm/MC/SubtargetFeature.h"
39#include "llvm/Support/Casting.h"
40#include "llvm/Support/Compiler.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000041#include "llvm/Support/Debug.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000042#include "llvm/Support/ELF.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000043#include "llvm/Support/ErrorHandling.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000044#include "llvm/Support/MathExtras.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000045#include "llvm/Support/raw_ostream.h"
46#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"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000049#include <algorithm>
50#include <cassert>
51#include <cstdint>
Toma Tabacu9db22db2014-09-09 10:15:38 +000052#include <memory>
Eugene Zelenkodde94e42017-01-30 23:21:32 +000053#include <string>
54#include <utility>
Rafael Espindola870c4e92012-01-11 03:56:41 +000055
56using namespace llvm;
57
Chandler Carruthe96dd892014-04-21 22:55:11 +000058#define DEBUG_TYPE "mips-asm-parser"
59
Joey Gouly0e76fa72013-09-12 10:28:05 +000060namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000061
Joey Gouly0e76fa72013-09-12 10:28:05 +000062class MCInstrInfo;
Eugene Zelenkodde94e42017-01-30 23:21:32 +000063
64} // end namespace llvm
Joey Gouly0e76fa72013-09-12 10:28:05 +000065
Rafael Espindola870c4e92012-01-11 03:56:41 +000066namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000067
Jack Carter0b744b32012-10-04 02:29:46 +000068class MipsAssemblerOptions {
69public:
Eugene Zelenkodde94e42017-01-30 23:21:32 +000070 MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000071
Toma Tabacu9db22db2014-09-09 10:15:38 +000072 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000073 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000074 Reorder = Opts->isReorder();
75 Macro = Opts->isMacro();
76 Features = Opts->getFeatures();
77 }
78
Toma Tabacub19cf202015-04-27 13:12:59 +000079 unsigned getATRegIndex() const { return ATReg; }
80 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000081 if (Reg > 31)
82 return false;
83
84 ATReg = Reg;
85 return true;
86 }
Jack Carter0b744b32012-10-04 02:29:46 +000087
Toma Tabacu9db22db2014-09-09 10:15:38 +000088 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000089 void setReorder() { Reorder = true; }
90 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000091
Toma Tabacu9db22db2014-09-09 10:15:38 +000092 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000093 void setMacro() { Macro = true; }
94 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000095
Toma Tabacu465acfd2015-06-09 13:33:26 +000096 const FeatureBitset &getFeatures() const { return Features; }
97 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000098
Daniel Sandersf0df2212014-08-04 12:20:00 +000099 // Set of features that are either architecture features or referenced
100 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
101 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
102 // The reason we need this mask is explained in the selectArch function.
103 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000104 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +0000105
Jack Carter0b744b32012-10-04 02:29:46 +0000106private:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000107 unsigned ATReg = 1;
108 bool Reorder = true;
109 bool Macro = true;
Toma Tabacu465acfd2015-06-09 13:33:26 +0000110 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +0000111};
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000112
113} // end anonymous namespace
Jack Carter0b744b32012-10-04 02:29:46 +0000114
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000115const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
116 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
117 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
118 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
119 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
120 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
121 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
122 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
123 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
124};
125
Jack Carter0b744b32012-10-04 02:29:46 +0000126namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000127
Rafael Espindola870c4e92012-01-11 03:56:41 +0000128class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000129 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000130 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000131 return static_cast<MipsTargetStreamer &>(TS);
132 }
133
Eric Christophera5762812015-01-26 17:33:46 +0000134 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000135 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000136 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
137 // nullptr, which indicates that no function is currently
138 // selected. This usually happens after an '.end func'
139 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000140 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000141 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000142 bool IsCpRestoreSet;
143 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000144 unsigned CpSaveLocation;
145 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
146 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000147
Daniel Sandersef638fe2014-10-03 15:37:37 +0000148 // Print a warning along with its fix-it message at the given range.
149 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
150 SMRange Range, bool ShowColors = true);
151
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000152#define GET_ASSEMBLER_HEADER
153#include "MipsGenAsmMatcher.inc"
154
Daniel Sandersc5537422016-07-27 13:49:44 +0000155 unsigned
156 checkEarlyTargetMatchPredicate(MCInst &Inst,
157 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000158 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
159
Chad Rosier49963552012-10-13 00:26:04 +0000160 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000161 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000162 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000163 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000164
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000165 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000166 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000167
Toma Tabacu13964452014-09-04 13:23:44 +0000168 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000169
Toma Tabacu13964452014-09-04 13:23:44 +0000170 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000171
Craig Topper55bc6cb2017-02-08 02:54:12 +0000172 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
173
David Blaikie960ea3f2014-06-08 16:18:35 +0000174 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
175 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000176
Craig Topper56c590a2014-04-29 07:58:02 +0000177 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000178
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000179 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
180 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000181 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000182 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000183 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
184 SMLoc S);
185 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
186 OperandMatchResultTy parseImm(OperandVector &Operands);
187 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
188 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000189 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
190 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
191 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000192
David Blaikie960ea3f2014-06-08 16:18:35 +0000193 bool searchSymbolAlias(OperandVector &Operands);
194
Toma Tabacu13964452014-09-04 13:23:44 +0000195 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000196
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000197 enum MacroExpanderResultTy {
198 MER_NotAMacro,
199 MER_Success,
200 MER_Fail,
201 };
Jack Carter30a59822012-10-04 04:03:53 +0000202
Matheus Almeida3813d572014-06-19 14:39:14 +0000203 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000204 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
205 MCStreamer &Out,
206 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000207
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000208 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
209 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000210
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000211 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000212 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000213 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000214
Toma Tabacuf712ede2015-06-17 14:31:51 +0000215 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
216 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000217 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000218
Toma Tabacu00e98672015-05-01 12:19:27 +0000219 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000220 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000221
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000222 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
223 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000224 SMLoc IDLoc, MCStreamer &Out,
225 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000226
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000227 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
228 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000229
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000230 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000231 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
232
233 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
234 const MCSubtargetInfo *STI, bool IsImmOpnd);
235
236 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
237 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000238
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000239 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
240 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000241
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000242 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
243 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000244
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000245 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
246 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000247
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000248 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
249 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000250
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000251 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
252 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000253 const bool Signed);
254
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000255 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000256 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000257
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000258 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
259 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000260
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000261 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
262 const MCSubtargetInfo *STI);
263
264 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000265 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000266
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000267 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000268 MCStreamer &Out, const MCSubtargetInfo *STI);
269 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
270 const MCSubtargetInfo *STI);
271 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
272 const MCSubtargetInfo *STI);
273 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
274 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000275
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000276 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
277 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000278
Simon Dardis3c82a642017-02-08 16:25:05 +0000279 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
280 const MCSubtargetInfo *STI);
281
282 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
283 const MCSubtargetInfo *STI);
284
285 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
286 const MCSubtargetInfo *STI);
287
288 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
289 const MCSubtargetInfo *STI);
290
Simon Dardisaff4d142016-10-18 14:28:00 +0000291 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
292 const MCSubtargetInfo *STI, bool IsLoad);
293
Simon Dardis43115a12016-11-21 20:30:41 +0000294 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
295 const MCSubtargetInfo *STI);
296
297 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
298 const MCSubtargetInfo *STI);
299
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000300 bool reportParseError(Twine ErrorMsg);
301 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000302
Jack Carterb5cf5902013-04-17 00:18:04 +0000303 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000304
305 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000306 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000307 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000308 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000309 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000310 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000311 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000312 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000313 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000314 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000315 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000316 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000317 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000318 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000319
320 bool parseSetAtDirective();
321 bool parseSetNoAtDirective();
322 bool parseSetMacroDirective();
323 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000324 bool parseSetMsaDirective();
325 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000326 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000327 bool parseSetReorderDirective();
328 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000329 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000330 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000331 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000332 bool parseSetOddSPRegDirective();
333 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000334 bool parseSetPopDirective();
335 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000336 bool parseSetSoftFloatDirective();
337 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000338
Jack Carterd76b2372013-03-21 21:44:16 +0000339 bool parseSetAssignment();
340
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000341 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000342 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000343 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000344 bool parseDirectiveDtpRelWord();
345 bool parseDirectiveDtpRelDWord();
346 bool parseDirectiveTpRelWord();
347 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000348 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000349 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000350 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
351 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000352
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000353 bool parseInternalDirectiveReallowModule();
354
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000355 bool eatComma(StringRef ErrorStr);
356
Jack Carter1ac53222013-02-20 23:11:17 +0000357 int matchCPURegisterName(StringRef Symbol);
358
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000359 int matchHWRegsRegisterName(StringRef Symbol);
360
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000361 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000362
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000363 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000364
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000365 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000366
Jack Carter5dc8ac92013-09-25 23:50:44 +0000367 int matchMSA128RegisterName(StringRef Name);
368
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000369 int matchMSA128CtrlRegisterName(StringRef Name);
370
Jack Carterd0bd6422013-04-18 00:41:53 +0000371 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000372
Toma Tabacu89a712b2015-04-15 10:48:56 +0000373 /// Returns the internal register number for the current AT. Also checks if
374 /// the current AT is unavailable (set to $0) and gives an error if it is.
375 /// This should be used in pseudo-instruction expansions which need AT.
376 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000377
Simon Dardis3aa8a902017-02-06 12:43:46 +0000378 bool canUseATReg();
379
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000380 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
381 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000382
383 // Helper function that checks if the value of a vector index is within the
384 // boundaries of accepted values for each RegisterKind
385 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
386 bool validateMSAIndex(int Val, int RegKind);
387
Daniel Sandersf0df2212014-08-04 12:20:00 +0000388 // Selects a new architecture by updating the FeatureBits with the necessary
389 // info including implied dependencies.
390 // Internally, it clears all the feature bits related to *any* architecture
391 // and selects the new one using the ToggleFeature functionality of the
392 // MCSubtargetInfo object that handles implied dependencies. The reason we
393 // clear all the arch related bits manually is because ToggleFeature only
394 // clears the features that imply the feature being cleared and not the
395 // features implied by the feature being cleared. This is easier to see
396 // with an example:
397 // --------------------------------------------------
398 // | Feature | Implies |
399 // | -------------------------------------------------|
400 // | FeatureMips1 | None |
401 // | FeatureMips2 | FeatureMips1 |
402 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
403 // | FeatureMips4 | FeatureMips3 |
404 // | ... | |
405 // --------------------------------------------------
406 //
407 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
408 // FeatureMipsGP64 | FeatureMips1)
409 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
410 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000411 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000412 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000413 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
414 STI.setFeatureBits(FeatureBits);
415 setAvailableFeatures(
416 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000417 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000418 }
419
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000420 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000421 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000422 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000423 setAvailableFeatures(
424 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000425 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000426 }
427 }
428
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000429 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000430 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000431 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000432 setAvailableFeatures(
433 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000434 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000435 }
436 }
437
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000438 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
439 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000440 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000441 }
442
443 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
444 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000445 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000446 }
447
Rafael Espindola870c4e92012-01-11 03:56:41 +0000448public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000449 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000450 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000451 Match_RequiresDifferentOperands,
452 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000453 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000454 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000455 Match_NonZeroOperandForSync,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000456#define GET_OPERAND_DIAGNOSTIC_TYPES
457#include "MipsGenAsmMatcher.inc"
458#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000459 };
460
Akira Hatanakab11ef082015-11-14 06:35:56 +0000461 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000462 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000463 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000464 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
465 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000466 MCAsmParserExtension::Initialize(parser);
467
Toma Tabacu11e14a92015-04-21 11:50:52 +0000468 parser.addAliasForDirective(".asciiz", ".asciz");
469
Jack Carterb4dbc172012-09-05 23:34:03 +0000470 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000471 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000472
Toma Tabacu9db22db2014-09-09 10:15:38 +0000473 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000474 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000475 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000476
Toma Tabacu9db22db2014-09-09 10:15:38 +0000477 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000478 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000479 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000480
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000481 getTargetStreamer().updateABIInfo(*this);
482
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000483 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000484 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000485
486 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000487
Rafael Espindola699281c2016-05-18 11:58:50 +0000488 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000489
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000490 IsCpRestoreSet = false;
491 CpRestoreOffset = -1;
492
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000493 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000494 if ((TheTriple.getArch() == Triple::mips) ||
495 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000496 IsLittleEndian = false;
497 else
498 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000499 }
500
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000501 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
502 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
503
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000504 bool isGP64bit() const {
505 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
506 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000507
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000508 bool isFP64bit() const {
509 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
510 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000511
Eric Christophera5762812015-01-26 17:33:46 +0000512 const MipsABIInfo &getABI() const { return ABI; }
513 bool isABI_N32() const { return ABI.IsN32(); }
514 bool isABI_N64() const { return ABI.IsN64(); }
515 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000516 bool isABI_FPXX() const {
517 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
518 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000519
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000520 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000521 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000522 }
523
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000524 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000525 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000526 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000527
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000528 bool hasMips1() const {
529 return getSTI().getFeatureBits()[Mips::FeatureMips1];
530 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000531
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000532 bool hasMips2() const {
533 return getSTI().getFeatureBits()[Mips::FeatureMips2];
534 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000535
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000536 bool hasMips3() const {
537 return getSTI().getFeatureBits()[Mips::FeatureMips3];
538 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000539
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000540 bool hasMips4() const {
541 return getSTI().getFeatureBits()[Mips::FeatureMips4];
542 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000543
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 bool hasMips5() const {
545 return getSTI().getFeatureBits()[Mips::FeatureMips5];
546 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000547
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000548 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000549 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000550 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000551
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000552 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000553 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000554 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000555
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000556 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000557 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000558 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000559
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000560 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000561 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000562 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000563
Daniel Sanders17793142015-02-18 16:24:50 +0000564 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000565 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000566 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000567
Daniel Sanders17793142015-02-18 16:24:50 +0000568 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000569 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000570 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000571
Daniel Sanders17793142015-02-18 16:24:50 +0000572 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000573 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000574 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000575
Daniel Sanders17793142015-02-18 16:24:50 +0000576 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000577 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000578 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000579
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000580 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000581 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000582 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000583
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000584 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000585 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000586 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000587
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000588 bool hasDSP() const {
589 return getSTI().getFeatureBits()[Mips::FeatureDSP];
590 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000591
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000592 bool hasDSPR2() const {
593 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
594 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000595
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000596 bool hasDSPR3() const {
597 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
598 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000599
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000600 bool hasMSA() const {
601 return getSTI().getFeatureBits()[Mips::FeatureMSA];
602 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000603
Kai Nackee0245392015-01-27 19:11:28 +0000604 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000605 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000606 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000607
Daniel Sandersa6994442015-08-18 12:33:54 +0000608 bool inPicMode() {
609 return IsPicEnabled;
610 }
611
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000612 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000613 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000614 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000615
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000616 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000617 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000618 }
619
Eric Christophere8ae3e32015-05-07 23:10:21 +0000620 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000621 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000622 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000623
Toma Tabacud9d344b2015-04-27 14:05:04 +0000624 /// Warn if RegIndex is the same as the current AT.
625 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000626
627 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000628
629 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000630
631 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
632 AsmToken::TokenKind OperatorToken,
633 MCContext &Ctx) override {
634 switch(OperatorToken) {
635 default:
636 llvm_unreachable("Unknown token");
637 return nullptr;
638 case AsmToken::PercentCall16:
639 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
640 case AsmToken::PercentCall_Hi:
641 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
642 case AsmToken::PercentCall_Lo:
643 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
644 case AsmToken::PercentDtprel_Hi:
645 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
646 case AsmToken::PercentDtprel_Lo:
647 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
648 case AsmToken::PercentGot:
649 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
650 case AsmToken::PercentGot_Disp:
651 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
652 case AsmToken::PercentGot_Hi:
653 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
654 case AsmToken::PercentGot_Lo:
655 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
656 case AsmToken::PercentGot_Ofst:
657 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
658 case AsmToken::PercentGot_Page:
659 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
660 case AsmToken::PercentGottprel:
661 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
662 case AsmToken::PercentGp_Rel:
663 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
664 case AsmToken::PercentHi:
665 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
666 case AsmToken::PercentHigher:
667 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
668 case AsmToken::PercentHighest:
669 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
670 case AsmToken::PercentLo:
671 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
672 case AsmToken::PercentNeg:
673 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
674 case AsmToken::PercentPcrel_Hi:
675 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
676 case AsmToken::PercentPcrel_Lo:
677 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
678 case AsmToken::PercentTlsgd:
679 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
680 case AsmToken::PercentTlsldm:
681 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
682 case AsmToken::PercentTprel_Hi:
683 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
684 case AsmToken::PercentTprel_Lo:
685 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
686 }
687 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000688};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000689
690/// MipsOperand - Instances of this class represent a parsed Mips machine
691/// instruction.
692class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000693public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000694 /// Broad categories of register classes
695 /// The exact class is finalized by the render method.
696 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000697 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000698 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000699 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000700 RegKind_FCC = 4, /// FCC
701 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
702 RegKind_MSACtrl = 16, /// MSA control registers
703 RegKind_COP2 = 32, /// COP2
704 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
705 /// context).
706 RegKind_CCR = 128, /// CCR
707 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000708 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000709 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000710 /// Potentially any (e.g. $1)
711 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
712 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000713 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000714 };
715
716private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000717 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000718 k_Immediate, /// An immediate (possibly involving symbol references)
719 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000720 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000721 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000722 k_RegList, /// A physical register list
723 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000724 } Kind;
725
David Blaikie960ea3f2014-06-08 16:18:35 +0000726public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000727 MipsOperand(KindTy K, MipsAsmParser &Parser)
728 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
729
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000730 ~MipsOperand() override {
731 switch (Kind) {
732 case k_Immediate:
733 break;
734 case k_Memory:
735 delete Mem.Base;
736 break;
737 case k_RegList:
738 delete RegList.List;
739 case k_RegisterIndex:
740 case k_Token:
741 case k_RegPair:
742 break;
743 }
744 }
745
David Blaikie960ea3f2014-06-08 16:18:35 +0000746private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000747 /// For diagnostics, and checking the assembler temporary
748 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000749
Eric Christopher8996c5d2013-03-15 00:42:55 +0000750 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000751 const char *Data;
752 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000753 };
754
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000755 struct RegIdxOp {
756 unsigned Index; /// Index into the register class
757 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000758 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000759 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000760 };
761
762 struct ImmOp {
763 const MCExpr *Val;
764 };
765
766 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000767 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000768 const MCExpr *Off;
769 };
770
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000771 struct RegListOp {
772 SmallVector<unsigned, 10> *List;
773 };
774
Jack Carterb4dbc172012-09-05 23:34:03 +0000775 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000776 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000777 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000778 struct ImmOp Imm;
779 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000780 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000781 };
782
783 SMLoc StartLoc, EndLoc;
784
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000786 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
787 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000788 const MCRegisterInfo *RegInfo,
789 SMLoc S, SMLoc E,
790 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000791 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000792 Op->RegIdx.Index = Index;
793 Op->RegIdx.RegInfo = RegInfo;
794 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000795 Op->RegIdx.Tok.Data = Str.data();
796 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000797 Op->StartLoc = S;
798 Op->EndLoc = E;
799 return Op;
800 }
801
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000802public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000803 /// Coerce the register to GPR32 and return the real register for the current
804 /// target.
805 unsigned getGPR32Reg() const {
806 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000807 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000808 unsigned ClassID = Mips::GPR32RegClassID;
809 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000810 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000811
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000812 /// Coerce the register to GPR32 and return the real register for the current
813 /// target.
814 unsigned getGPRMM16Reg() const {
815 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
816 unsigned ClassID = Mips::GPR32RegClassID;
817 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
818 }
819
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000820 /// Coerce the register to GPR64 and return the real register for the current
821 /// target.
822 unsigned getGPR64Reg() const {
823 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
824 unsigned ClassID = Mips::GPR64RegClassID;
825 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000826 }
827
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000828private:
829 /// Coerce the register to AFGR64 and return the real register for the current
830 /// target.
831 unsigned getAFGR64Reg() const {
832 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
833 if (RegIdx.Index % 2 != 0)
834 AsmParser.Warning(StartLoc, "Float register should be even.");
835 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
836 .getRegister(RegIdx.Index / 2);
837 }
838
839 /// Coerce the register to FGR64 and return the real register for the current
840 /// target.
841 unsigned getFGR64Reg() const {
842 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
843 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
844 .getRegister(RegIdx.Index);
845 }
846
847 /// Coerce the register to FGR32 and return the real register for the current
848 /// target.
849 unsigned getFGR32Reg() const {
850 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
851 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
852 .getRegister(RegIdx.Index);
853 }
854
855 /// Coerce the register to FGRH32 and return the real register for the current
856 /// target.
857 unsigned getFGRH32Reg() const {
858 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
859 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
860 .getRegister(RegIdx.Index);
861 }
862
863 /// Coerce the register to FCC and return the real register for the current
864 /// target.
865 unsigned getFCCReg() const {
866 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
867 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
868 .getRegister(RegIdx.Index);
869 }
870
871 /// Coerce the register to MSA128 and return the real register for the current
872 /// target.
873 unsigned getMSA128Reg() const {
874 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
875 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
876 // identical
877 unsigned ClassID = Mips::MSA128BRegClassID;
878 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
879 }
880
881 /// Coerce the register to MSACtrl and return the real register for the
882 /// current target.
883 unsigned getMSACtrlReg() const {
884 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
885 unsigned ClassID = Mips::MSACtrlRegClassID;
886 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
887 }
888
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000889 /// Coerce the register to COP0 and return the real register for the
890 /// current target.
891 unsigned getCOP0Reg() const {
892 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
893 unsigned ClassID = Mips::COP0RegClassID;
894 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
895 }
896
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000897 /// Coerce the register to COP2 and return the real register for the
898 /// current target.
899 unsigned getCOP2Reg() const {
900 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
901 unsigned ClassID = Mips::COP2RegClassID;
902 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
903 }
904
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000905 /// Coerce the register to COP3 and return the real register for the
906 /// current target.
907 unsigned getCOP3Reg() const {
908 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
909 unsigned ClassID = Mips::COP3RegClassID;
910 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
911 }
912
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000913 /// Coerce the register to ACC64DSP and return the real register for the
914 /// current target.
915 unsigned getACC64DSPReg() const {
916 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
917 unsigned ClassID = Mips::ACC64DSPRegClassID;
918 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
919 }
920
921 /// Coerce the register to HI32DSP and return the real register for the
922 /// current target.
923 unsigned getHI32DSPReg() const {
924 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
925 unsigned ClassID = Mips::HI32DSPRegClassID;
926 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
927 }
928
929 /// Coerce the register to LO32DSP and return the real register for the
930 /// current target.
931 unsigned getLO32DSPReg() const {
932 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
933 unsigned ClassID = Mips::LO32DSPRegClassID;
934 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
935 }
936
937 /// Coerce the register to CCR and return the real register for the
938 /// current target.
939 unsigned getCCRReg() const {
940 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
941 unsigned ClassID = Mips::CCRRegClassID;
942 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
943 }
944
945 /// Coerce the register to HWRegs and return the real register for the
946 /// current target.
947 unsigned getHWRegsReg() const {
948 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
949 unsigned ClassID = Mips::HWRegsRegClassID;
950 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
951 }
952
953public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000954 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000955 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000956 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000957 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000958 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000959 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000960 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000961 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000962 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000963
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000964 void addRegOperands(MCInst &Inst, unsigned N) const {
965 llvm_unreachable("Use a custom parser instead");
966 }
967
Daniel Sanders21bce302014-04-01 12:35:23 +0000968 /// Render the operand to an MCInst as a GPR32
969 /// Asserts if the wrong number of operands are requested, or the operand
970 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +0000971 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
972 assert(N == 1 && "Invalid number of operands!");
973 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
974 }
975
976 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
977 assert(N == 1 && "Invalid number of operands!");
978 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
979 }
980
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000981 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
982 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000983 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000984 }
985
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000986 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
987 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000988 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000989 }
990
Jozef Kolek1904fa22014-11-24 14:25:53 +0000991 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
992 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000993 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000994 }
995
Zoran Jovanovic41688672015-02-10 16:36:20 +0000996 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
997 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000998 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000999 }
1000
Daniel Sanders21bce302014-04-01 12:35:23 +00001001 /// Render the operand to an MCInst as a GPR64
1002 /// Asserts if the wrong number of operands are requested, or the operand
1003 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001004 void addGPR64AsmRegOperands(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(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001007 }
1008
1009 void addAFGR64AsmRegOperands(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(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001012 }
1013
1014 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1015 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001016 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001017 }
1018
1019 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1020 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001021 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001022 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001023 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001024 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001025 AsmParser.getParser().printError(
1026 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1027 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001028 }
1029
1030 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1031 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001032 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001033 }
1034
1035 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1036 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001037 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001038 }
1039
1040 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1041 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001042 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001043 }
1044
1045 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1046 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001047 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001048 }
1049
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001050 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1051 assert(N == 1 && "Invalid number of operands!");
1052 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1053 }
1054
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001055 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1056 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001057 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001058 }
1059
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001060 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1061 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001062 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001063 }
1064
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001065 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1066 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001067 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001068 }
1069
1070 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1071 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001072 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001073 }
1074
1075 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1076 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001077 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001078 }
1079
1080 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1081 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001082 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001083 }
1084
1085 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1086 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001087 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001088 }
1089
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001090 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001091 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1092 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001093 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001094 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001095 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001096 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001097 Inst.addOperand(MCOperand::createImm(Imm));
1098 }
1099
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001100 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001101 void addSImmOperands(MCInst &Inst, unsigned N) const {
1102 if (isImm() && !isConstantImm()) {
1103 addExpr(Inst, getImm());
1104 return;
1105 }
1106 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1107 }
1108
1109 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001110 void addUImmOperands(MCInst &Inst, unsigned N) const {
1111 if (isImm() && !isConstantImm()) {
1112 addExpr(Inst, getImm());
1113 return;
1114 }
1115 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1116 }
1117
Daniel Sanders78e89022016-03-11 11:37:50 +00001118 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1119 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1120 assert(N == 1 && "Invalid number of operands!");
1121 int64_t Imm = getConstantImm() - Offset;
1122 Imm = SignExtend64<Bits>(Imm);
1123 Imm += Offset;
1124 Imm += AdjustOffset;
1125 Inst.addOperand(MCOperand::createImm(Imm));
1126 }
1127
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001128 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001129 assert(N == 1 && "Invalid number of operands!");
1130 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001131 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001132 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001133
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001134 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001135 assert(N == 2 && "Invalid number of operands!");
1136
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001137 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1138 ? getMemBase()->getGPR64Reg()
1139 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001140
1141 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001142 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001143 }
1144
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001145 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1146 assert(N == 2 && "Invalid number of operands!");
1147
Jim Grosbache9119e42015-05-13 18:37:00 +00001148 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001149
1150 const MCExpr *Expr = getMemOff();
1151 addExpr(Inst, Expr);
1152 }
1153
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001154 void addRegListOperands(MCInst &Inst, unsigned N) const {
1155 assert(N == 1 && "Invalid number of operands!");
1156
1157 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001158 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001159 }
1160
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001161 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1162 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001163 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001164 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001165 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1166 Inst.addOperand(MCOperand::createReg(
1167 RegIdx.RegInfo->getRegClass(
1168 AsmParser.getABI().AreGprs64bit()
1169 ? Mips::GPR64RegClassID
1170 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1171 Inst.addOperand(MCOperand::createReg(
1172 RegIdx.RegInfo->getRegClass(
1173 AsmParser.getABI().AreGprs64bit()
1174 ? Mips::GPR64RegClassID
1175 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001176 }
1177
Zoran Jovanovic41688672015-02-10 16:36:20 +00001178 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1179 assert(N == 2 && "Invalid number of operands!");
1180 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001181 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001182 }
1183
Craig Topper56c590a2014-04-29 07:58:02 +00001184 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001185 // As a special case until we sort out the definition of div/divu, accept
1186 // $0/$zero here so that MCK_ZERO works correctly.
1187 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001188 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001189
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001190 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001191 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001192
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001193 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001194 int64_t Res;
1195 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001196 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001197
Daniel Sanders52da7af2015-11-06 12:11:03 +00001198 bool isConstantImmz() const {
1199 return isConstantImm() && getConstantImm() == 0;
1200 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001201
Daniel Sandersea4f6532015-11-06 12:22:31 +00001202 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1203 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1204 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001205
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001206 template <unsigned Bits> bool isSImm() const {
1207 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1208 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001209
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001210 template <unsigned Bits> bool isUImm() const {
1211 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1212 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001213
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001214 template <unsigned Bits> bool isAnyImm() const {
1215 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1216 isUInt<Bits>(getConstantImm()))
1217 : isImm();
1218 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001219
Daniel Sanders78e89022016-03-11 11:37:50 +00001220 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1221 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001222 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001223
Hrvoje Varga46458d02016-02-25 12:53:29 +00001224 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1225 return isConstantImm() && getConstantImm() >= Bottom &&
1226 getConstantImm() <= Top;
1227 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001228
Craig Topper56c590a2014-04-29 07:58:02 +00001229 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001230 // Note: It's not possible to pretend that other operand kinds are tokens.
1231 // The matcher emitter checks tokens first.
1232 return Kind == k_Token;
1233 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001234
Craig Topper56c590a2014-04-29 07:58:02 +00001235 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001236
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001237 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001238 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001239 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001240
Simon Dardis4ccda502016-05-27 13:56:36 +00001241 // Allow relocation operators.
1242 // FIXME: This predicate and others need to look through binary expressions
1243 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001244 template <unsigned Bits, unsigned ShiftAmount = 0>
1245 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001246 if (!isMem())
1247 return false;
1248 if (!getMemBase()->isGPRAsmReg())
1249 return false;
1250 if (isa<MCTargetExpr>(getMemOff()) ||
1251 (isConstantMemOff() &&
1252 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1253 return true;
1254 MCValue Res;
1255 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1256 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001257 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001258
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001259 bool isMemWithGRPMM16Base() const {
1260 return isMem() && getMemBase()->isMM16AsmReg();
1261 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001262
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001263 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1264 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1265 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1266 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001267
Jozef Kolek12c69822014-12-23 16:16:33 +00001268 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1269 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1270 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1271 && (getMemBase()->getGPR32Reg() == Mips::SP);
1272 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001273
Daniel Sanderse473dc92016-05-09 13:38:25 +00001274 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1275 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1276 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1277 && (getMemBase()->getGPR32Reg() == Mips::GP);
1278 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001279
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001280 template <unsigned Bits, unsigned ShiftLeftAmount>
1281 bool isScaledUImm() const {
1282 return isConstantImm() &&
1283 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001284 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001285
Daniel Sanders97297772016-03-22 14:40:00 +00001286 template <unsigned Bits, unsigned ShiftLeftAmount>
1287 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001288 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1289 return true;
1290 // Operand can also be a symbol or symbol plus offset in case of relocations.
1291 if (Kind != k_Immediate)
1292 return false;
1293 MCValue Res;
1294 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1295 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001296 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001297
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001298 bool isRegList16() const {
1299 if (!isRegList())
1300 return false;
1301
1302 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001303 if (Size < 2 || Size > 5)
1304 return false;
1305
1306 unsigned R0 = RegList.List->front();
1307 unsigned R1 = RegList.List->back();
1308 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1309 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001310 return false;
1311
1312 int PrevReg = *RegList.List->begin();
1313 for (int i = 1; i < Size - 1; i++) {
1314 int Reg = (*(RegList.List))[i];
1315 if ( Reg != PrevReg + 1)
1316 return false;
1317 PrevReg = Reg;
1318 }
1319
1320 return true;
1321 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001322
Vladimir Medic2b953d02013-10-01 09:48:56 +00001323 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001324
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001325 bool isLSAImm() const {
1326 if (!isConstantImm())
1327 return false;
1328 int64_t Val = getConstantImm();
1329 return 1 <= Val && Val <= 4;
1330 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001331
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001332 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001333
Zoran Jovanovic41688672015-02-10 16:36:20 +00001334 bool isMovePRegPair() const {
1335 if (Kind != k_RegList || RegList.List->size() != 2)
1336 return false;
1337
1338 unsigned R0 = RegList.List->front();
1339 unsigned R1 = RegList.List->back();
1340
1341 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1342 (R0 == Mips::A1 && R1 == Mips::A3) ||
1343 (R0 == Mips::A2 && R1 == Mips::A3) ||
1344 (R0 == Mips::A0 && R1 == Mips::S5) ||
1345 (R0 == Mips::A0 && R1 == Mips::S6) ||
1346 (R0 == Mips::A0 && R1 == Mips::A1) ||
1347 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001348 (R0 == Mips::A0 && R1 == Mips::A3) ||
1349 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1350 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1351 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1352 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1353 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1354 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1355 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1356 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001357 return true;
1358
1359 return false;
1360 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001361
1362 StringRef getToken() const {
1363 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001364 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001365 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001366
Zlatko Buljanba553a62016-05-09 08:07:28 +00001367 bool isRegPair() const {
1368 return Kind == k_RegPair && RegIdx.Index <= 30;
1369 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001370
Craig Topper56c590a2014-04-29 07:58:02 +00001371 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001372 // As a special case until we sort out the definition of div/divu, accept
1373 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001374 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1375 RegIdx.Kind & RegKind_GPR)
1376 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001377
Daniel Sanders976d9382016-07-05 13:38:40 +00001378 llvm_unreachable("Invalid access!");
1379 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001380 }
1381
Jack Carterb4dbc172012-09-05 23:34:03 +00001382 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001383 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001384 return Imm.Val;
1385 }
1386
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001387 int64_t getConstantImm() const {
1388 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001389 int64_t Value = 0;
1390 (void)Val->evaluateAsAbsolute(Value);
1391 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001392 }
1393
1394 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001395 assert((Kind == k_Memory) && "Invalid access!");
1396 return Mem.Base;
1397 }
1398
1399 const MCExpr *getMemOff() const {
1400 assert((Kind == k_Memory) && "Invalid access!");
1401 return Mem.Off;
1402 }
1403
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001404 int64_t getConstantMemOff() const {
1405 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1406 }
1407
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001408 const SmallVectorImpl<unsigned> &getRegList() const {
1409 assert((Kind == k_RegList) && "Invalid access!");
1410 return *(RegList.List);
1411 }
1412
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001413 unsigned getRegPair() const {
1414 assert((Kind == k_RegPair) && "Invalid access!");
1415 return RegIdx.Index;
1416 }
1417
David Blaikie960ea3f2014-06-08 16:18:35 +00001418 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1419 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001420 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001421 Op->Tok.Data = Str.data();
1422 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001423 Op->StartLoc = S;
1424 Op->EndLoc = S;
1425 return Op;
1426 }
1427
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001428 /// Create a numeric register (e.g. $1). The exact register remains
1429 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001430 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001431 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1432 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001433 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001434 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001435 }
1436
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001437 /// Create a register that is definitely a GPR.
1438 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001439 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001440 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1441 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1442 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001443 }
1444
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001445 /// Create a register that is definitely a FGR.
1446 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001447 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001448 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1449 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1450 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001451 }
1452
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001453 /// Create a register that is definitely a HWReg.
1454 /// This is typically only used for named registers such as $hwr_cpunum.
1455 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001456 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001457 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001458 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001459 }
1460
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001461 /// Create a register that is definitely an FCC.
1462 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001463 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001464 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1465 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1466 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001467 }
1468
1469 /// Create a register that is definitely an ACC.
1470 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001471 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001472 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1473 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1474 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001475 }
1476
1477 /// Create a register that is definitely an MSA128.
1478 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001479 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001480 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1481 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1482 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001483 }
1484
1485 /// Create a register that is definitely an MSACtrl.
1486 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001487 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001488 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1489 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1490 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001491 }
1492
David Blaikie960ea3f2014-06-08 16:18:35 +00001493 static std::unique_ptr<MipsOperand>
1494 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001495 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001496 Op->Imm.Val = Val;
1497 Op->StartLoc = S;
1498 Op->EndLoc = E;
1499 return Op;
1500 }
1501
David Blaikie960ea3f2014-06-08 16:18:35 +00001502 static std::unique_ptr<MipsOperand>
1503 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1504 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001505 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001506 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001507 Op->Mem.Off = Off;
1508 Op->StartLoc = S;
1509 Op->EndLoc = E;
1510 return Op;
1511 }
1512
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001513 static std::unique_ptr<MipsOperand>
1514 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1515 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001516 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001517
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001518 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001519 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001520 Op->StartLoc = StartLoc;
1521 Op->EndLoc = EndLoc;
1522 return Op;
1523 }
1524
Daniel Sandersd044e492016-05-09 13:10:57 +00001525 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1526 SMLoc S, SMLoc E,
1527 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001528 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001529 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001530 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1531 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001532 Op->StartLoc = S;
1533 Op->EndLoc = E;
1534 return Op;
1535 }
1536
Simon Dardis509da1a2017-02-13 16:06:48 +00001537 bool isGPRZeroAsmReg() const {
1538 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1539 }
1540
1541 bool isGPRNonZeroAsmReg() const {
1542 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1543 RegIdx.Index <= 31;
1544 }
1545
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001546 bool isGPRAsmReg() const {
1547 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001548 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001549
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001550 bool isMM16AsmReg() const {
1551 if (!(isRegIdx() && RegIdx.Kind))
1552 return false;
1553 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1554 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001555
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001556 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001557 bool isMM16AsmRegZero() const {
1558 if (!(isRegIdx() && RegIdx.Kind))
1559 return false;
1560 return (RegIdx.Index == 0 ||
1561 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1562 RegIdx.Index == 17);
1563 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001564
Zoran Jovanovic41688672015-02-10 16:36:20 +00001565 bool isMM16AsmRegMoveP() const {
1566 if (!(isRegIdx() && RegIdx.Kind))
1567 return false;
1568 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1569 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1570 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001571
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001572 bool isFGRAsmReg() const {
1573 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1574 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001575 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001576
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001577 bool isHWRegsAsmReg() const {
1578 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001579 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001580
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001581 bool isCCRAsmReg() const {
1582 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001583 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001584
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001585 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001586 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1587 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001588 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001589 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001590
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001591 bool isACCAsmReg() const {
1592 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001593 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001594
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001595 bool isCOP0AsmReg() const {
1596 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1597 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001598
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001599 bool isCOP2AsmReg() const {
1600 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001601 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001602
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001603 bool isCOP3AsmReg() const {
1604 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1605 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001606
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001607 bool isMSA128AsmReg() const {
1608 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001609 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001610
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001611 bool isMSACtrlAsmReg() const {
1612 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001613 }
1614
Jack Carterb4dbc172012-09-05 23:34:03 +00001615 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001616 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001617 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001618 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001619
Craig Topper56c590a2014-04-29 07:58:02 +00001620 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001621 switch (Kind) {
1622 case k_Immediate:
1623 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001624 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001625 OS << ">";
1626 break;
1627 case k_Memory:
1628 OS << "Mem<";
1629 Mem.Base->print(OS);
1630 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001631 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001632 OS << ">";
1633 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001634 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001635 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1636 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001637 break;
1638 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001639 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001640 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001641 case k_RegList:
1642 OS << "RegList< ";
1643 for (auto Reg : (*RegList.List))
1644 OS << Reg << " ";
1645 OS << ">";
1646 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001647 case k_RegPair:
1648 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1649 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001650 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001651 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001652
1653 bool isValidForTie(const MipsOperand &Other) const {
1654 if (Kind != Other.Kind)
1655 return false;
1656
1657 switch (Kind) {
1658 default:
1659 llvm_unreachable("Unexpected kind");
1660 return false;
1661 case k_RegisterIndex: {
1662 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1663 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1664 return Token == OtherToken;
1665 }
1666 }
1667 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001668}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001669
1670} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001671
Jack Carter9e65aa32013-03-22 00:05:30 +00001672namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001673
Jack Carter9e65aa32013-03-22 00:05:30 +00001674extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001675
1676} // end namespace llvm
1677
Jack Carter9e65aa32013-03-22 00:05:30 +00001678static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1679 return MipsInsts[Opcode];
1680}
1681
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001682static bool hasShortDelaySlot(unsigned Opcode) {
1683 switch (Opcode) {
1684 case Mips::JALS_MM:
1685 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001686 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001687 case Mips::BGEZALS_MM:
1688 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001689 return true;
1690 default:
1691 return false;
1692 }
1693}
1694
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001695static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1696 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1697 return &SRExpr->getSymbol();
1698 }
1699
1700 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1701 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1702 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1703
1704 if (LHSSym)
1705 return LHSSym;
1706
1707 if (RHSSym)
1708 return RHSSym;
1709
1710 return nullptr;
1711 }
1712
1713 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1714 return getSingleMCSymbol(UExpr->getSubExpr());
1715
1716 return nullptr;
1717}
1718
1719static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1720 if (isa<MCSymbolRefExpr>(Expr))
1721 return 1;
1722
1723 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1724 return countMCSymbolRefExpr(BExpr->getLHS()) +
1725 countMCSymbolRefExpr(BExpr->getRHS());
1726
1727 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1728 return countMCSymbolRefExpr(UExpr->getSubExpr());
1729
1730 return 0;
1731}
1732
Jack Carter9e65aa32013-03-22 00:05:30 +00001733bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001734 MCStreamer &Out,
1735 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001736 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001737 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001738 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001739
Jack Carter9e65aa32013-03-22 00:05:30 +00001740 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001741
1742 if (MCID.isBranch() || MCID.isCall()) {
1743 const unsigned Opcode = Inst.getOpcode();
1744 MCOperand Offset;
1745
1746 switch (Opcode) {
1747 default:
1748 break;
Kai Nackee0245392015-01-27 19:11:28 +00001749 case Mips::BBIT0:
1750 case Mips::BBIT032:
1751 case Mips::BBIT1:
1752 case Mips::BBIT132:
1753 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001754 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001755
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001756 case Mips::BEQ:
1757 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001758 case Mips::BEQ_MM:
1759 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001760 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001761 Offset = Inst.getOperand(2);
1762 if (!Offset.isImm())
1763 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001764 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001765 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001766 if (OffsetToAlignment(Offset.getImm(),
1767 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001768 return Error(IDLoc, "branch to misaligned address");
1769 break;
1770 case Mips::BGEZ:
1771 case Mips::BGTZ:
1772 case Mips::BLEZ:
1773 case Mips::BLTZ:
1774 case Mips::BGEZAL:
1775 case Mips::BLTZAL:
1776 case Mips::BC1F:
1777 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001778 case Mips::BGEZ_MM:
1779 case Mips::BGTZ_MM:
1780 case Mips::BLEZ_MM:
1781 case Mips::BLTZ_MM:
1782 case Mips::BGEZAL_MM:
1783 case Mips::BLTZAL_MM:
1784 case Mips::BC1F_MM:
1785 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001786 case Mips::BC1EQZC_MMR6:
1787 case Mips::BC1NEZC_MMR6:
1788 case Mips::BC2EQZC_MMR6:
1789 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001790 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001791 Offset = Inst.getOperand(1);
1792 if (!Offset.isImm())
1793 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001794 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001795 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001796 if (OffsetToAlignment(Offset.getImm(),
1797 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001798 return Error(IDLoc, "branch to misaligned address");
1799 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001800 case Mips::BGEC: case Mips::BGEC_MMR6:
1801 case Mips::BLTC: case Mips::BLTC_MMR6:
1802 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1803 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1804 case Mips::BEQC: case Mips::BEQC_MMR6:
1805 case Mips::BNEC: case Mips::BNEC_MMR6:
1806 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1807 Offset = Inst.getOperand(2);
1808 if (!Offset.isImm())
1809 break; // We'll deal with this situation later on when applying fixups.
1810 if (!isIntN(18, Offset.getImm()))
1811 return Error(IDLoc, "branch target out of range");
1812 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1813 return Error(IDLoc, "branch to misaligned address");
1814 break;
1815 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1816 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1817 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1818 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1819 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1820 Offset = Inst.getOperand(1);
1821 if (!Offset.isImm())
1822 break; // We'll deal with this situation later on when applying fixups.
1823 if (!isIntN(18, Offset.getImm()))
1824 return Error(IDLoc, "branch target out of range");
1825 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1826 return Error(IDLoc, "branch to misaligned address");
1827 break;
1828 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1829 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1830 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1831 Offset = Inst.getOperand(1);
1832 if (!Offset.isImm())
1833 break; // We'll deal with this situation later on when applying fixups.
1834 if (!isIntN(23, Offset.getImm()))
1835 return Error(IDLoc, "branch target out of range");
1836 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1837 return Error(IDLoc, "branch to misaligned address");
1838 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001839 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001840 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001841 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001842 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001843 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1844 Offset = Inst.getOperand(1);
1845 if (!Offset.isImm())
1846 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001847 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001848 return Error(IDLoc, "branch target out of range");
1849 if (OffsetToAlignment(Offset.getImm(), 2LL))
1850 return Error(IDLoc, "branch to misaligned address");
1851 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001852 }
1853 }
1854
Daniel Sandersa84989a2014-06-16 13:25:35 +00001855 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1856 // We still accept it but it is a normal nop.
1857 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1858 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1859 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1860 "nop instruction");
1861 }
1862
Kai Nackee0245392015-01-27 19:11:28 +00001863 if (hasCnMips()) {
1864 const unsigned Opcode = Inst.getOpcode();
1865 MCOperand Opnd;
1866 int Imm;
1867
1868 switch (Opcode) {
1869 default:
1870 break;
1871
1872 case Mips::BBIT0:
1873 case Mips::BBIT032:
1874 case Mips::BBIT1:
1875 case Mips::BBIT132:
1876 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1877 // The offset is handled above
1878 Opnd = Inst.getOperand(1);
1879 if (!Opnd.isImm())
1880 return Error(IDLoc, "expected immediate operand kind");
1881 Imm = Opnd.getImm();
1882 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1883 Opcode == Mips::BBIT1 ? 63 : 31))
1884 return Error(IDLoc, "immediate operand value out of range");
1885 if (Imm > 31) {
1886 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1887 : Mips::BBIT132);
1888 Inst.getOperand(1).setImm(Imm - 32);
1889 }
1890 break;
1891
Kai Nackee0245392015-01-27 19:11:28 +00001892 case Mips::SEQi:
1893 case Mips::SNEi:
1894 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1895 Opnd = Inst.getOperand(2);
1896 if (!Opnd.isImm())
1897 return Error(IDLoc, "expected immediate operand kind");
1898 Imm = Opnd.getImm();
1899 if (!isInt<10>(Imm))
1900 return Error(IDLoc, "immediate operand value out of range");
1901 break;
1902 }
1903 }
1904
Simon Dardis509da1a2017-02-13 16:06:48 +00001905 // Warn on division by zero. We're checking here as all instructions get
1906 // processed here, not just the macros that need expansion.
1907 //
1908 // The MIPS backend models most of the divison instructions and macros as
1909 // three operand instructions. The pre-R6 divide instructions however have
1910 // two operands and explicitly define HI/LO as part of the instruction,
1911 // not in the operands.
1912 unsigned FirstOp = 1;
1913 unsigned SecondOp = 2;
1914 switch (Inst.getOpcode()) {
1915 default:
1916 break;
1917 case Mips::SDivIMacro:
1918 case Mips::UDivIMacro:
1919 case Mips::DSDivIMacro:
1920 case Mips::DUDivIMacro:
1921 if (Inst.getOperand(2).getImm() == 0) {
1922 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1923 Inst.getOperand(1).getReg() == Mips::ZERO_64)
1924 Warning(IDLoc, "dividing zero by zero");
1925 else
1926 Warning(IDLoc, "division by zero");
1927 }
1928 break;
1929 case Mips::DSDIV:
1930 case Mips::SDIV:
1931 case Mips::UDIV:
1932 case Mips::DUDIV:
1933 case Mips::UDIV_MM:
1934 case Mips::SDIV_MM:
1935 FirstOp = 0;
1936 SecondOp = 1;
1937 case Mips::SDivMacro:
1938 case Mips::DSDivMacro:
1939 case Mips::UDivMacro:
1940 case Mips::DUDivMacro:
1941 case Mips::DIV:
1942 case Mips::DIVU:
1943 case Mips::DDIV:
1944 case Mips::DDIVU:
1945 case Mips::DIVU_MMR6:
1946 case Mips::DDIVU_MM64R6:
1947 case Mips::DIV_MMR6:
1948 case Mips::DDIV_MM64R6:
1949 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
1950 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
1951 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
1952 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
1953 Warning(IDLoc, "dividing zero by zero");
1954 else
1955 Warning(IDLoc, "division by zero");
1956 }
1957 break;
1958 }
1959
Simon Atanasyan50485142016-12-12 17:40:26 +00001960 // For PIC code convert unconditional jump to unconditional branch.
1961 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
1962 inPicMode()) {
1963 MCInst BInst;
1964 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
1965 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1966 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1967 BInst.addOperand(Inst.getOperand(0));
1968 Inst = BInst;
1969 }
1970
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001971 // This expansion is not in a function called by tryExpandInstruction()
1972 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001973 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1974 inPicMode()) {
1975 warnIfNoMacro(IDLoc);
1976
1977 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1978
1979 // We can do this expansion if there's only 1 symbol in the argument
1980 // expression.
1981 if (countMCSymbolRefExpr(JalExpr) > 1)
1982 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1983
1984 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001985 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001986 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1987
1988 // FIXME: Add support for label+offset operands (currently causes an error).
1989 // FIXME: Add support for forward-declared local symbols.
1990 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00001991 if (JalSym->isInSection() || JalSym->isTemporary() ||
1992 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001993 if (isABI_O32()) {
1994 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001995 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001996 // R_(MICRO)MIPS_GOT16 label
1997 // addiu $25, $25, 0
1998 // R_(MICRO)MIPS_LO16 label
1999 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002000 const MCExpr *Got16RelocExpr =
2001 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2002 const MCExpr *Lo16RelocExpr =
2003 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002004
Daniel Sandersa736b372016-04-29 13:33:12 +00002005 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2006 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2007 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2008 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002009 } else if (isABI_N32() || isABI_N64()) {
2010 // If it's a local symbol and the N32/N64 ABIs are being used,
2011 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002012 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002013 // R_(MICRO)MIPS_GOT_DISP label
2014 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002015 const MCExpr *GotDispRelocExpr =
2016 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002017
Daniel Sandersa736b372016-04-29 13:33:12 +00002018 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2019 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2020 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002021 }
2022 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002023 // If it's an external/weak symbol, we expand to:
2024 // lw/ld $25, 0($gp)
2025 // R_(MICRO)MIPS_CALL16 label
2026 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002027 const MCExpr *Call16RelocExpr =
2028 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002029
Daniel Sandersa736b372016-04-29 13:33:12 +00002030 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2031 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002032 }
2033
2034 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002035 if (IsCpRestoreSet && inMicroMipsMode())
2036 JalrInst.setOpcode(Mips::JALRS_MM);
2037 else
2038 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002039 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2040 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2041
2042 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2043 // This relocation is supposed to be an optimization hint for the linker
2044 // and is not necessary for correctness.
2045
2046 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002047 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002048 }
2049
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002050 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2051 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002052 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002053 // reference or immediate we may have to expand instructions.
2054 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002055 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002056 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2057 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002058 MCOperand &Op = Inst.getOperand(i);
2059 if (Op.isImm()) {
2060 int MemOffset = Op.getImm();
2061 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002062 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002063 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00002064 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002065 }
2066 } else if (Op.isExpr()) {
2067 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002068 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002069 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002070 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002071 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002072 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002073 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002074 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002075 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002076 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002077 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002078 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002079 }
2080 }
2081 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002082 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002083 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002084
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002085 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002086 if (MCID.mayLoad()) {
2087 // Try to create 16-bit GP relative load instruction.
2088 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2089 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2090 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2091 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2092 MCOperand &Op = Inst.getOperand(i);
2093 if (Op.isImm()) {
2094 int MemOffset = Op.getImm();
2095 MCOperand &DstReg = Inst.getOperand(0);
2096 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002097 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002098 getContext().getRegisterInfo()->getRegClass(
2099 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002100 (BaseReg.getReg() == Mips::GP ||
2101 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002102
Daniel Sandersa736b372016-04-29 13:33:12 +00002103 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2104 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002105 return false;
2106 }
2107 }
2108 }
2109 } // for
2110 } // if load
2111
2112 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2113
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002114 MCOperand Opnd;
2115 int Imm;
2116
2117 switch (Inst.getOpcode()) {
2118 default:
2119 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002120 case Mips::ADDIUSP_MM:
2121 Opnd = Inst.getOperand(0);
2122 if (!Opnd.isImm())
2123 return Error(IDLoc, "expected immediate operand kind");
2124 Imm = Opnd.getImm();
2125 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2126 Imm % 4 != 0)
2127 return Error(IDLoc, "immediate operand value out of range");
2128 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002129 case Mips::SLL16_MM:
2130 case Mips::SRL16_MM:
2131 Opnd = Inst.getOperand(2);
2132 if (!Opnd.isImm())
2133 return Error(IDLoc, "expected immediate operand kind");
2134 Imm = Opnd.getImm();
2135 if (Imm < 1 || Imm > 8)
2136 return Error(IDLoc, "immediate operand value out of range");
2137 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002138 case Mips::LI16_MM:
2139 Opnd = Inst.getOperand(1);
2140 if (!Opnd.isImm())
2141 return Error(IDLoc, "expected immediate operand kind");
2142 Imm = Opnd.getImm();
2143 if (Imm < -1 || Imm > 126)
2144 return Error(IDLoc, "immediate operand value out of range");
2145 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002146 case Mips::ADDIUR2_MM:
2147 Opnd = Inst.getOperand(2);
2148 if (!Opnd.isImm())
2149 return Error(IDLoc, "expected immediate operand kind");
2150 Imm = Opnd.getImm();
2151 if (!(Imm == 1 || Imm == -1 ||
2152 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2153 return Error(IDLoc, "immediate operand value out of range");
2154 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002155 case Mips::ANDI16_MM:
2156 Opnd = Inst.getOperand(2);
2157 if (!Opnd.isImm())
2158 return Error(IDLoc, "expected immediate operand kind");
2159 Imm = Opnd.getImm();
2160 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2161 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2162 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2163 return Error(IDLoc, "immediate operand value out of range");
2164 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002165 case Mips::LBU16_MM:
2166 Opnd = Inst.getOperand(2);
2167 if (!Opnd.isImm())
2168 return Error(IDLoc, "expected immediate operand kind");
2169 Imm = Opnd.getImm();
2170 if (Imm < -1 || Imm > 14)
2171 return Error(IDLoc, "immediate operand value out of range");
2172 break;
2173 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002174 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002175 Opnd = Inst.getOperand(2);
2176 if (!Opnd.isImm())
2177 return Error(IDLoc, "expected immediate operand kind");
2178 Imm = Opnd.getImm();
2179 if (Imm < 0 || Imm > 15)
2180 return Error(IDLoc, "immediate operand value out of range");
2181 break;
2182 case Mips::LHU16_MM:
2183 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002184 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002185 Opnd = Inst.getOperand(2);
2186 if (!Opnd.isImm())
2187 return Error(IDLoc, "expected immediate operand kind");
2188 Imm = Opnd.getImm();
2189 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2190 return Error(IDLoc, "immediate operand value out of range");
2191 break;
2192 case Mips::LW16_MM:
2193 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002194 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002195 Opnd = Inst.getOperand(2);
2196 if (!Opnd.isImm())
2197 return Error(IDLoc, "expected immediate operand kind");
2198 Imm = Opnd.getImm();
2199 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2200 return Error(IDLoc, "immediate operand value out of range");
2201 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002202 case Mips::ADDIUPC_MM:
2203 MCOperand Opnd = Inst.getOperand(1);
2204 if (!Opnd.isImm())
2205 return Error(IDLoc, "expected immediate operand kind");
2206 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002207 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002208 return Error(IDLoc, "immediate operand value out of range");
2209 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002210 }
2211 }
2212
Daniel Sandersd8c07762016-04-18 12:35:36 +00002213 bool FillDelaySlot =
2214 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2215 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002216 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002217
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002218 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002219 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002220 switch (ExpandResult) {
2221 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002222 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002223 break;
2224 case MER_Success:
2225 break;
2226 case MER_Fail:
2227 return true;
2228 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002229
Daniel Sanderscda908a2016-05-16 09:10:13 +00002230 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2231 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2232 if (inMicroMipsMode())
2233 TOut.setUsesMicroMips();
2234
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002235 // If this instruction has a delay slot and .set reorder is active,
2236 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002237 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002238 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2239 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002240 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002241
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002242 if ((Inst.getOpcode() == Mips::JalOneReg ||
2243 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2244 isPicAndNotNxxAbi()) {
2245 if (IsCpRestoreSet) {
2246 // We need a NOP between the JALR and the LW:
2247 // If .set reorder has been used, we've already emitted a NOP.
2248 // If .set noreorder has been used, we need to emit a NOP at this point.
2249 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002250 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2251 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002252
2253 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002254 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002255 } else
2256 Warning(IDLoc, "no .cprestore used in PIC mode");
2257 }
2258
Jack Carter9e65aa32013-03-22 00:05:30 +00002259 return false;
2260}
2261
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002262MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002263MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2264 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002265 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002266 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002267 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002268 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002269 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002270 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002271 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002272 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002273 case Mips::LoadAddrImm64:
2274 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2275 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2276 "expected immediate operand kind");
2277
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002278 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2279 Inst.getOperand(1),
2280 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002281 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002282 ? MER_Fail
2283 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002284 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002285 case Mips::LoadAddrReg64:
2286 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2287 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2288 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2289 "expected immediate operand kind");
2290
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002291 return expandLoadAddress(Inst.getOperand(0).getReg(),
2292 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2293 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002294 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002295 ? MER_Fail
2296 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002297 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002298 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002299 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2300 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002301 case Mips::SWM_MM:
2302 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002303 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2304 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002305 case Mips::JalOneReg:
2306 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002307 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002308 case Mips::BneImm:
2309 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002310 case Mips::BEQLImmMacro:
2311 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002312 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002313 case Mips::BLT:
2314 case Mips::BLE:
2315 case Mips::BGE:
2316 case Mips::BGT:
2317 case Mips::BLTU:
2318 case Mips::BLEU:
2319 case Mips::BGEU:
2320 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002321 case Mips::BLTL:
2322 case Mips::BLEL:
2323 case Mips::BGEL:
2324 case Mips::BGTL:
2325 case Mips::BLTUL:
2326 case Mips::BLEUL:
2327 case Mips::BGEUL:
2328 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002329 case Mips::BLTImmMacro:
2330 case Mips::BLEImmMacro:
2331 case Mips::BGEImmMacro:
2332 case Mips::BGTImmMacro:
2333 case Mips::BLTUImmMacro:
2334 case Mips::BLEUImmMacro:
2335 case Mips::BGEUImmMacro:
2336 case Mips::BGTUImmMacro:
2337 case Mips::BLTLImmMacro:
2338 case Mips::BLELImmMacro:
2339 case Mips::BGELImmMacro:
2340 case Mips::BGTLImmMacro:
2341 case Mips::BLTULImmMacro:
2342 case Mips::BLEULImmMacro:
2343 case Mips::BGEULImmMacro:
2344 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002345 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002346 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002347 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002348 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2349 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002350 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002351 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002352 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2353 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002354 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002355 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002356 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2357 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002358 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002359 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002360 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2361 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002362 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002363 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2364 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002365 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002366 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002367 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002368 case Mips::PseudoTRUNC_W_D:
2369 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2370 : MER_Success;
2371 case Mips::Ulh:
2372 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2373 case Mips::Ulhu:
2374 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002375 case Mips::Ush:
2376 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002377 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002378 case Mips::Usw:
2379 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002380 case Mips::NORImm:
2381 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002382 case Mips::ADDi: case Mips::ADDi_MM:
2383 case Mips::ADDiu: case Mips::ADDiu_MM:
2384 case Mips::SLTi: case Mips::SLTi_MM:
2385 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002386 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2387 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2388 int64_t ImmValue = Inst.getOperand(2).getImm();
2389 if (isInt<16>(ImmValue))
2390 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002391 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2392 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002393 }
2394 return MER_NotAMacro;
Simon Dardisd410fc82017-02-23 12:40:58 +00002395 case Mips::ANDi: case Mips::ANDi_MM:
2396 case Mips::ORi: case Mips::ORi_MM:
2397 case Mips::XORi: case Mips::XORi_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002398 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2399 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2400 int64_t ImmValue = Inst.getOperand(2).getImm();
2401 if (isUInt<16>(ImmValue))
2402 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002403 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2404 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002405 }
2406 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002407 case Mips::ROL:
2408 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002409 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002410 case Mips::ROLImm:
2411 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002412 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002413 case Mips::DROL:
2414 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002415 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002416 case Mips::DROLImm:
2417 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002418 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002419 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002420 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002421 case Mips::MULImmMacro:
2422 case Mips::DMULImmMacro:
2423 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2424 case Mips::MULOMacro:
2425 case Mips::DMULOMacro:
2426 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2427 case Mips::MULOUMacro:
2428 case Mips::DMULOUMacro:
2429 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2430 case Mips::DMULMacro:
2431 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002432 case Mips::LDMacro:
2433 case Mips::SDMacro:
2434 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2435 Inst.getOpcode() == Mips::LDMacro)
2436 ? MER_Fail
2437 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002438 case Mips::SEQMacro:
2439 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2440 case Mips::SEQIMacro:
2441 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002442 }
Jack Carter30a59822012-10-04 04:03:53 +00002443}
Jack Carter92995f12012-10-06 00:53:28 +00002444
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002445bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002446 MCStreamer &Out,
2447 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002448 MipsTargetStreamer &TOut = getTargetStreamer();
2449
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002450 // Create a JALR instruction which is going to replace the pseudo-JAL.
2451 MCInst JalrInst;
2452 JalrInst.setLoc(IDLoc);
2453 const MCOperand FirstRegOp = Inst.getOperand(0);
2454 const unsigned Opcode = Inst.getOpcode();
2455
2456 if (Opcode == Mips::JalOneReg) {
2457 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002458 if (IsCpRestoreSet && inMicroMipsMode()) {
2459 JalrInst.setOpcode(Mips::JALRS16_MM);
2460 JalrInst.addOperand(FirstRegOp);
2461 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002462 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002463 JalrInst.addOperand(FirstRegOp);
2464 } else {
2465 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002466 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002467 JalrInst.addOperand(FirstRegOp);
2468 }
2469 } else if (Opcode == Mips::JalTwoReg) {
2470 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002471 if (IsCpRestoreSet && inMicroMipsMode())
2472 JalrInst.setOpcode(Mips::JALRS_MM);
2473 else
2474 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002475 JalrInst.addOperand(FirstRegOp);
2476 const MCOperand SecondRegOp = Inst.getOperand(1);
2477 JalrInst.addOperand(SecondRegOp);
2478 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002479 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002480
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002481 // If .set reorder is active and branch instruction has a delay slot,
2482 // emit a NOP after it.
2483 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002484 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2485 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2486 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002487
2488 return false;
2489}
2490
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002491/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002492template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002493 unsigned BitNum = findFirstSet(x);
2494
2495 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2496}
2497
2498/// Load (or add) an immediate into a register.
2499///
2500/// @param ImmValue The immediate to load.
2501/// @param DstReg The register that will hold the immediate.
2502/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2503/// for a simple initialization.
2504/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2505/// @param IsAddress True if the immediate represents an address. False if it
2506/// is an integer.
2507/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002508bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002509 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002510 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2511 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002512 MipsTargetStreamer &TOut = getTargetStreamer();
2513
Toma Tabacu00e98672015-05-01 12:19:27 +00002514 if (!Is32BitImm && !isGP64bit()) {
2515 Error(IDLoc, "instruction requires a 64-bit architecture");
2516 return true;
2517 }
2518
Daniel Sanders03f9c012015-07-14 12:24:22 +00002519 if (Is32BitImm) {
2520 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2521 // Sign extend up to 64-bit so that the predicates match the hardware
2522 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2523 // true.
2524 ImmValue = SignExtend64<32>(ImmValue);
2525 } else {
2526 Error(IDLoc, "instruction requires a 32-bit immediate");
2527 return true;
2528 }
2529 }
2530
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002531 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2532 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2533
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002534 bool UseSrcReg = false;
2535 if (SrcReg != Mips::NoRegister)
2536 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002537
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002538 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002539 if (UseSrcReg &&
2540 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002541 // At this point we need AT to perform the expansions and we exit if it is
2542 // not available.
2543 unsigned ATReg = getATReg(IDLoc);
2544 if (!ATReg)
2545 return true;
2546 TmpReg = ATReg;
2547 }
2548
Daniel Sanders03f9c012015-07-14 12:24:22 +00002549 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002550 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002551 SrcReg = ZeroReg;
2552
2553 // This doesn't quite follow the usual ABI expectations for N32 but matches
2554 // traditional assembler behaviour. N32 would normally use addiu for both
2555 // integers and addresses.
2556 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002557 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002558 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002559 }
2560
Daniel Sandersa736b372016-04-29 13:33:12 +00002561 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002562 return false;
2563 }
2564
2565 if (isUInt<16>(ImmValue)) {
2566 unsigned TmpReg = DstReg;
2567 if (SrcReg == DstReg) {
2568 TmpReg = getATReg(IDLoc);
2569 if (!TmpReg)
2570 return true;
2571 }
2572
Daniel Sandersa736b372016-04-29 13:33:12 +00002573 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002574 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002575 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002576 return false;
2577 }
2578
2579 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002580 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002581
Toma Tabacu79588102015-04-29 10:19:56 +00002582 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2583 uint16_t Bits15To0 = ImmValue & 0xffff;
2584
Toma Tabacua3d056f2015-05-15 09:42:11 +00002585 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002586 // Traditional behaviour seems to special case this particular value. It's
2587 // not clear why other masks are handled differently.
2588 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002589 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2590 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002591 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002592 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002593 return false;
2594 }
2595
2596 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002597 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002598 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2599 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002600 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002601 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002602 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002603 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002604 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002605 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002606
Daniel Sandersa736b372016-04-29 13:33:12 +00002607 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002608 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002609 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002610 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002611 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002612 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002613 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002614
2615 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2616 if (Is32BitImm) {
2617 Error(IDLoc, "instruction requires a 32-bit immediate");
2618 return true;
2619 }
2620
2621 // Traditionally, these immediates are shifted as little as possible and as
2622 // such we align the most significant bit to bit 15 of our temporary.
2623 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2624 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2625 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2626 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002627 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2628 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002629
2630 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002631 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002632
2633 return false;
2634 }
2635
2636 warnIfNoMacro(IDLoc);
2637
2638 // The remaining case is packed with a sequence of dsll and ori with zeros
2639 // being omitted and any neighbouring dsll's being coalesced.
2640 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2641
2642 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2643 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002644 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002645 return false;
2646
2647 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2648 // skip it and defer the shift to the next chunk.
2649 unsigned ShiftCarriedForwards = 16;
2650 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2651 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2652
2653 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002654 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2655 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002656 ShiftCarriedForwards = 0;
2657 }
2658
2659 ShiftCarriedForwards += 16;
2660 }
2661 ShiftCarriedForwards -= 16;
2662
2663 // Finish any remaining shifts left by trailing zeros.
2664 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002665 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002666
2667 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002668 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002669
Matheus Almeida3813d572014-06-19 14:39:14 +00002670 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002671}
Jack Carter92995f12012-10-06 00:53:28 +00002672
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002673bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002674 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002675 const MCOperand &ImmOp = Inst.getOperand(1);
2676 assert(ImmOp.isImm() && "expected immediate operand kind");
2677 const MCOperand &DstRegOp = Inst.getOperand(0);
2678 assert(DstRegOp.isReg() && "expected register operand kind");
2679
2680 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002681 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002682 return true;
2683
2684 return false;
2685}
2686
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002687bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2688 const MCOperand &Offset,
2689 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002690 MCStreamer &Out,
2691 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002692 // la can't produce a usable address when addresses are 64-bit.
2693 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2694 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2695 // We currently can't do this because we depend on the equality
2696 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2697 Error(IDLoc, "la used to load 64-bit address");
2698 // Continue as if we had 'dla' instead.
2699 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002700 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002701 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002702
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002703 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002704 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002705 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002706 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002707 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002708
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002709 if (!Offset.isImm())
2710 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002711 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002712
Scott Egerton24557012016-01-21 15:11:01 +00002713 if (!ABI.ArePtrs64bit()) {
2714 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2715 Is32BitAddress = true;
2716 }
2717
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002718 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002719 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002720}
2721
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002722bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2723 unsigned DstReg, unsigned SrcReg,
2724 bool Is32BitSym, SMLoc IDLoc,
2725 MCStreamer &Out,
2726 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002727 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002728 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002729 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002730
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002731 if (inPicMode() && ABI.IsO32()) {
2732 MCValue Res;
2733 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2734 Error(IDLoc, "expected relocatable expression");
2735 return true;
2736 }
2737 if (Res.getSymB() != nullptr) {
2738 Error(IDLoc, "expected relocatable expression with only one symbol");
2739 return true;
2740 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002741
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002742 // The case where the result register is $25 is somewhat special. If the
2743 // symbol in the final relocation is external and not modified with a
2744 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2745 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2746 Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
2747 !Res.getSymA()->getSymbol().isTemporary()) {
2748 const MCExpr *CallExpr =
2749 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2750 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2751 MCOperand::createExpr(CallExpr), IDLoc, STI);
2752 return false;
2753 }
2754
2755 // The remaining cases are:
2756 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2757 // >addiu $tmp, $tmp, %lo(offset)
2758 // >addiu $rd, $tmp, $rs
2759 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2760 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2761 // >addiu $rd, $tmp, $rs
2762 // The addiu's marked with a '>' may be omitted if they are redundant. If
2763 // this happens then the last instruction must use $rd as the result
2764 // register.
2765 const MipsMCExpr *GotExpr =
2766 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2767 const MCExpr *LoExpr = nullptr;
2768 if (Res.getSymA()->getSymbol().isInSection() ||
2769 Res.getSymA()->getSymbol().isTemporary())
2770 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2771 else if (Res.getConstant() != 0) {
2772 // External symbols fully resolve the symbol with just the %got(symbol)
2773 // but we must still account for any offset to the symbol for expressions
2774 // like symbol+8.
2775 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2776 }
2777
2778 unsigned TmpReg = DstReg;
2779 if (UseSrcReg &&
2780 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2781 SrcReg)) {
2782 // If $rs is the same as $rd, we need to use AT.
2783 // If it is not available we exit.
2784 unsigned ATReg = getATReg(IDLoc);
2785 if (!ATReg)
2786 return true;
2787 TmpReg = ATReg;
2788 }
2789
2790 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2791 MCOperand::createExpr(GotExpr), IDLoc, STI);
2792
2793 if (LoExpr)
2794 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2795 IDLoc, STI);
2796
2797 if (UseSrcReg)
2798 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2799
2800 return false;
2801 }
2802
2803 const MipsMCExpr *HiExpr =
2804 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2805 const MipsMCExpr *LoExpr =
2806 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002807
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002808 // This is the 64-bit symbol address expansion.
2809 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00002810 // We need AT for the 64-bit expansion in the cases where the optional
2811 // source register is the destination register and for the superscalar
2812 // scheduled form.
2813 //
2814 // If it is not available we exit if the destination is the same as the
2815 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002816
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002817 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002818 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002819 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002820 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002821
Simon Dardis3aa8a902017-02-06 12:43:46 +00002822 bool RdRegIsRsReg =
2823 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
2824
2825 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
2826 unsigned ATReg = getATReg(IDLoc);
2827
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002828 // If $rs is the same as $rd:
2829 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2830 // daddiu $at, $at, %higher(sym)
2831 // dsll $at, $at, 16
2832 // daddiu $at, $at, %hi(sym)
2833 // dsll $at, $at, 16
2834 // daddiu $at, $at, %lo(sym)
2835 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002836 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2837 STI);
2838 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2839 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2840 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2841 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2842 IDLoc, STI);
2843 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2844 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2845 IDLoc, STI);
2846 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002847
2848 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00002849 } else if (canUseATReg() && !RdRegIsRsReg) {
2850 unsigned ATReg = getATReg(IDLoc);
2851
2852 // If the $rs is different from $rd or if $rs isn't specified and we
2853 // have $at available:
2854 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2855 // lui $at, %hi(sym)
2856 // daddiu $rd, $rd, %higher(sym)
2857 // daddiu $at, $at, %lo(sym)
2858 // dsll32 $rd, $rd, 0
2859 // daddu $rd, $rd, $at
2860 // (daddu $rd, $rd, $rs)
2861 //
2862 // Which is preferred for superscalar issue.
2863 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2864 STI);
2865 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2866 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2867 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2868 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2869 IDLoc, STI);
2870 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2871 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
2872 if (UseSrcReg)
2873 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
2874
2875 return false;
2876 } else if (!canUseATReg() && !RdRegIsRsReg) {
2877 // Otherwise, synthesize the address in the destination register
2878 // serially:
2879 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2880 // daddiu $rd, $rd, %higher(sym)
2881 // dsll $rd, $rd, 16
2882 // daddiu $rd, $rd, %hi(sym)
2883 // dsll $rd, $rd, 16
2884 // daddiu $rd, $rd, %lo(sym)
2885 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2886 STI);
2887 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2888 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2889 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
2890 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2891 MCOperand::createExpr(HiExpr), IDLoc, STI);
2892 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
2893 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2894 MCOperand::createExpr(LoExpr), IDLoc, STI);
2895 if (UseSrcReg)
2896 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
2897
2898 return false;
2899 } else {
2900 // We have a case where SrcReg == DstReg and we don't have $at
2901 // available. We can't expand this case, so error out appropriately.
2902 assert(SrcReg == DstReg && !canUseATReg() &&
2903 "Could have expanded dla but didn't?");
2904 reportParseError(IDLoc,
2905 "pseudo-instruction requires $at, which is not available");
2906 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002907 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002908 }
2909
2910 // And now, the 32-bit symbol address expansion:
2911 // If $rs is the same as $rd:
2912 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2913 // ori $at, $at, %lo(sym)
2914 // addu $rd, $at, $rd
2915 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2916 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2917 // ori $rd, $rd, %lo(sym)
2918 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002919 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002920 if (UseSrcReg &&
2921 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002922 // If $rs is the same as $rd, we need to use AT.
2923 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002924 unsigned ATReg = getATReg(IDLoc);
2925 if (!ATReg)
2926 return true;
2927 TmpReg = ATReg;
2928 }
2929
Daniel Sandersa736b372016-04-29 13:33:12 +00002930 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2931 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2932 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002933
Toma Tabacufb9d1252015-06-22 12:08:39 +00002934 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002935 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002936 else
Scott Egerton24557012016-01-21 15:11:01 +00002937 assert(
2938 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002939
Toma Tabacu674825c2015-06-16 12:16:24 +00002940 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002941}
2942
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002943bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2944 MCStreamer &Out,
2945 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002946 MipsTargetStreamer &TOut = getTargetStreamer();
2947
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002948 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2949 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002950
2951 MCOperand Offset = Inst.getOperand(0);
2952 if (Offset.isExpr()) {
2953 Inst.clear();
2954 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002955 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2956 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2957 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002958 } else {
2959 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002960 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002961 // If offset fits into 11 bits then this instruction becomes microMIPS
2962 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002963 if (inMicroMipsMode())
2964 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002965 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002966 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00002967 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002968 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00002969 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002970 Inst.clear();
2971 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002972 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2973 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2974 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002975 }
2976 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002977 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002978
Zoran Jovanovicada70912015-09-07 11:56:37 +00002979 // If .set reorder is active and branch instruction has a delay slot,
2980 // emit a NOP after it.
2981 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2982 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002983 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002984
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002985 return false;
2986}
2987
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002988bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2989 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002990 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002991 const MCOperand &DstRegOp = Inst.getOperand(0);
2992 assert(DstRegOp.isReg() && "expected register operand kind");
2993
2994 const MCOperand &ImmOp = Inst.getOperand(1);
2995 assert(ImmOp.isImm() && "expected immediate operand kind");
2996
2997 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002998 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2999 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003000
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003001 bool IsLikely = false;
3002
Toma Tabacue1e460d2015-06-11 10:36:10 +00003003 unsigned OpCode = 0;
3004 switch(Inst.getOpcode()) {
3005 case Mips::BneImm:
3006 OpCode = Mips::BNE;
3007 break;
3008 case Mips::BeqImm:
3009 OpCode = Mips::BEQ;
3010 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003011 case Mips::BEQLImmMacro:
3012 OpCode = Mips::BEQL;
3013 IsLikely = true;
3014 break;
3015 case Mips::BNELImmMacro:
3016 OpCode = Mips::BNEL;
3017 IsLikely = true;
3018 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003019 default:
3020 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3021 break;
3022 }
3023
3024 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003025 if (ImmValue == 0) {
3026 if (IsLikely) {
3027 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3028 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3029 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3030 } else
3031 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3032 STI);
3033 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003034 warnIfNoMacro(IDLoc);
3035
3036 unsigned ATReg = getATReg(IDLoc);
3037 if (!ATReg)
3038 return true;
3039
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003040 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003041 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003042 return true;
3043
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003044 if (IsLikely) {
3045 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3046 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3047 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3048 } else
3049 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003050 }
3051 return false;
3052}
3053
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003054void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00003055 const MCSubtargetInfo *STI, bool IsLoad,
3056 bool IsImmOpnd) {
3057 if (IsLoad) {
3058 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3059 return;
Scott Egertond65377d2016-03-17 10:37:51 +00003060 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003061 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3062}
3063
3064void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3065 const MCSubtargetInfo *STI, bool IsImmOpnd) {
3066 MipsTargetStreamer &TOut = getTargetStreamer();
3067
3068 unsigned DstReg = Inst.getOperand(0).getReg();
3069 unsigned BaseReg = Inst.getOperand(1).getReg();
3070
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003071 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003072 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3073 unsigned DstRegClassID =
3074 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3075 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3076 (DstRegClassID == Mips::GPR64RegClassID);
3077
3078 if (IsImmOpnd) {
3079 // Try to use DstReg as the temporary.
3080 if (IsGPR && (BaseReg != DstReg)) {
3081 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3082 Inst.getOperand(2).getImm(), DstReg, IDLoc,
3083 STI);
3084 return;
3085 }
3086
Matheus Almeida7de68e72014-06-18 14:46:05 +00003087 // At this point we need AT to perform the expansions and we exit if it is
3088 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00003089 unsigned ATReg = getATReg(IDLoc);
3090 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00003091 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003092
3093 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3094 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
3095 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00003096 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00003097
Daniel Sandersfba875f2016-04-29 13:43:45 +00003098 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003099 MCOperand LoOperand = MCOperand::createExpr(
3100 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3101 MCOperand HiOperand = MCOperand::createExpr(
3102 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003103
3104 // Try to use DstReg as the temporary.
3105 if (IsGPR && (BaseReg != DstReg)) {
3106 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3107 LoOperand, DstReg, IDLoc, STI);
3108 return;
3109 }
3110
3111 // At this point we need AT to perform the expansions and we exit if it is
3112 // not available.
3113 unsigned ATReg = getATReg(IDLoc);
3114 if (!ATReg)
3115 return;
3116
3117 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3118 LoOperand, ATReg, IDLoc, STI);
3119}
3120
3121void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3122 const MCSubtargetInfo *STI,
3123 bool IsImmOpnd) {
3124 MipsTargetStreamer &TOut = getTargetStreamer();
3125
3126 unsigned SrcReg = Inst.getOperand(0).getReg();
3127 unsigned BaseReg = Inst.getOperand(1).getReg();
3128
Daniel Sanders241c6792016-05-12 14:01:50 +00003129 if (IsImmOpnd) {
3130 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
3131 Inst.getOperand(2).getImm(),
3132 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3133 return;
3134 }
3135
Daniel Sandersfba875f2016-04-29 13:43:45 +00003136 unsigned ATReg = getATReg(IDLoc);
3137 if (!ATReg)
3138 return;
3139
Daniel Sandersfba875f2016-04-29 13:43:45 +00003140 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003141 MCOperand LoOperand = MCOperand::createExpr(
3142 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3143 MCOperand HiOperand = MCOperand::createExpr(
3144 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003145 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3146 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003147}
3148
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003149bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3150 MCStreamer &Out,
3151 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003152 unsigned OpNum = Inst.getNumOperands();
3153 unsigned Opcode = Inst.getOpcode();
3154 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3155
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003156 assert(Inst.getOperand(OpNum - 1).isImm() &&
3157 Inst.getOperand(OpNum - 2).isReg() &&
3158 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003159
3160 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3161 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003162 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3163 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3164 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3165 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003166 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003167 if (inMicroMipsMode() && hasMips32r6())
3168 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3169 else
3170 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3171 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003172
3173 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003174 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003175 return false;
3176}
3177
Toma Tabacu1a108322015-06-17 13:20:24 +00003178bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003179 MCStreamer &Out,
3180 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003181 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003182 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003183 unsigned PseudoOpcode = Inst.getOpcode();
3184 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003185 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003186 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3187
3188 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003189 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003190
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003191 unsigned TrgReg;
3192 if (TrgOp.isReg())
3193 TrgReg = TrgOp.getReg();
3194 else if (TrgOp.isImm()) {
3195 warnIfNoMacro(IDLoc);
3196 EmittedNoMacroWarning = true;
3197
3198 TrgReg = getATReg(IDLoc);
3199 if (!TrgReg)
3200 return true;
3201
3202 switch(PseudoOpcode) {
3203 default:
3204 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3205 case Mips::BLTImmMacro:
3206 PseudoOpcode = Mips::BLT;
3207 break;
3208 case Mips::BLEImmMacro:
3209 PseudoOpcode = Mips::BLE;
3210 break;
3211 case Mips::BGEImmMacro:
3212 PseudoOpcode = Mips::BGE;
3213 break;
3214 case Mips::BGTImmMacro:
3215 PseudoOpcode = Mips::BGT;
3216 break;
3217 case Mips::BLTUImmMacro:
3218 PseudoOpcode = Mips::BLTU;
3219 break;
3220 case Mips::BLEUImmMacro:
3221 PseudoOpcode = Mips::BLEU;
3222 break;
3223 case Mips::BGEUImmMacro:
3224 PseudoOpcode = Mips::BGEU;
3225 break;
3226 case Mips::BGTUImmMacro:
3227 PseudoOpcode = Mips::BGTU;
3228 break;
3229 case Mips::BLTLImmMacro:
3230 PseudoOpcode = Mips::BLTL;
3231 break;
3232 case Mips::BLELImmMacro:
3233 PseudoOpcode = Mips::BLEL;
3234 break;
3235 case Mips::BGELImmMacro:
3236 PseudoOpcode = Mips::BGEL;
3237 break;
3238 case Mips::BGTLImmMacro:
3239 PseudoOpcode = Mips::BGTL;
3240 break;
3241 case Mips::BLTULImmMacro:
3242 PseudoOpcode = Mips::BLTUL;
3243 break;
3244 case Mips::BLEULImmMacro:
3245 PseudoOpcode = Mips::BLEUL;
3246 break;
3247 case Mips::BGEULImmMacro:
3248 PseudoOpcode = Mips::BGEUL;
3249 break;
3250 case Mips::BGTULImmMacro:
3251 PseudoOpcode = Mips::BGTUL;
3252 break;
3253 }
3254
3255 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003256 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003257 return true;
3258 }
3259
Toma Tabacu1a108322015-06-17 13:20:24 +00003260 switch (PseudoOpcode) {
3261 case Mips::BLT:
3262 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003263 case Mips::BLTL:
3264 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003265 AcceptsEquality = false;
3266 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003267 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3268 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003269 ZeroSrcOpcode = Mips::BGTZ;
3270 ZeroTrgOpcode = Mips::BLTZ;
3271 break;
3272 case Mips::BLE:
3273 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003274 case Mips::BLEL:
3275 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003276 AcceptsEquality = true;
3277 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003278 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3279 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003280 ZeroSrcOpcode = Mips::BGEZ;
3281 ZeroTrgOpcode = Mips::BLEZ;
3282 break;
3283 case Mips::BGE:
3284 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003285 case Mips::BGEL:
3286 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003287 AcceptsEquality = true;
3288 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003289 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3290 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003291 ZeroSrcOpcode = Mips::BLEZ;
3292 ZeroTrgOpcode = Mips::BGEZ;
3293 break;
3294 case Mips::BGT:
3295 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003296 case Mips::BGTL:
3297 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003298 AcceptsEquality = false;
3299 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003300 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3301 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003302 ZeroSrcOpcode = Mips::BLTZ;
3303 ZeroTrgOpcode = Mips::BGTZ;
3304 break;
3305 default:
3306 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3307 }
3308
Toma Tabacu1a108322015-06-17 13:20:24 +00003309 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3310 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3311 if (IsSrcRegZero && IsTrgRegZero) {
3312 // FIXME: All of these Opcode-specific if's are needed for compatibility
3313 // with GAS' behaviour. However, they may not generate the most efficient
3314 // code in some circumstances.
3315 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003316 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3317 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003318 return false;
3319 }
3320 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003321 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3322 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003323 Warning(IDLoc, "branch is always taken");
3324 return false;
3325 }
3326 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003327 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3328 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003329 Warning(IDLoc, "branch is always taken");
3330 return false;
3331 }
3332 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003333 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3334 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003335 return false;
3336 }
3337 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003338 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3339 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003340 return false;
3341 }
3342 if (AcceptsEquality) {
3343 // If both registers are $0 and the pseudo-branch accepts equality, it
3344 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003345 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3346 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003347 Warning(IDLoc, "branch is always taken");
3348 return false;
3349 }
3350 // If both registers are $0 and the pseudo-branch does not accept
3351 // equality, it will never be taken, so we don't have to emit anything.
3352 return false;
3353 }
3354 if (IsSrcRegZero || IsTrgRegZero) {
3355 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3356 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3357 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3358 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3359 // the pseudo-branch will never be taken, so we don't emit anything.
3360 // This only applies to unsigned pseudo-branches.
3361 return false;
3362 }
3363 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3364 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3365 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3366 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3367 // the pseudo-branch will always be taken, so we emit an unconditional
3368 // branch.
3369 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003370 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3371 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003372 Warning(IDLoc, "branch is always taken");
3373 return false;
3374 }
3375 if (IsUnsigned) {
3376 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3377 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3378 // the pseudo-branch will be taken only when the non-zero register is
3379 // different from 0, so we emit a BNEZ.
3380 //
3381 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3382 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3383 // the pseudo-branch will be taken only when the non-zero register is
3384 // equal to 0, so we emit a BEQZ.
3385 //
3386 // Because only BLEU and BGEU branch on equality, we can use the
3387 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003388 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3389 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3390 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003391 return false;
3392 }
3393 // If we have a signed pseudo-branch and one of the registers is $0,
3394 // we can use an appropriate compare-to-zero branch. We select which one
3395 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003396 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3397 IsSrcRegZero ? TrgReg : SrcReg,
3398 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003399 return false;
3400 }
3401
3402 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3403 // expansions. If it is not available, we return.
3404 unsigned ATRegNum = getATReg(IDLoc);
3405 if (!ATRegNum)
3406 return true;
3407
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003408 if (!EmittedNoMacroWarning)
3409 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003410
3411 // SLT fits well with 2 of our 4 pseudo-branches:
3412 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3413 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3414 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3415 // This is accomplished by using a BNEZ with the result of the SLT.
3416 //
3417 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3418 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3419 // Because only BGE and BLE branch on equality, we can use the
3420 // AcceptsEquality variable to decide when to emit the BEQZ.
3421 // Note that the order of the SLT arguments doesn't change between
3422 // opposites.
3423 //
3424 // The same applies to the unsigned variants, except that SLTu is used
3425 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003426 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3427 ReverseOrderSLT ? TrgReg : SrcReg,
3428 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003429
Daniel Sandersa736b372016-04-29 13:33:12 +00003430 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3431 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3432 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3433 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003434 return false;
3435}
3436
Simon Dardis509da1a2017-02-13 16:06:48 +00003437// Expand a integer division macro.
3438//
3439// Notably we don't have to emit a warning when encountering $rt as the $zero
3440// register, or 0 as an immediate. processInstruction() has already done that.
3441//
3442// The destination register can only be $zero when expanding (S)DivIMacro or
3443// D(S)DivMacro.
3444
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003445bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3446 const MCSubtargetInfo *STI, const bool IsMips64,
3447 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003448 MipsTargetStreamer &TOut = getTargetStreamer();
3449
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003450 warnIfNoMacro(IDLoc);
3451
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003452 const MCOperand &RdRegOp = Inst.getOperand(0);
3453 assert(RdRegOp.isReg() && "expected register operand kind");
3454 unsigned RdReg = RdRegOp.getReg();
3455
3456 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003457 assert(RsRegOp.isReg() && "expected register operand kind");
3458 unsigned RsReg = RsRegOp.getReg();
3459
Simon Dardis12850ee2017-01-31 10:49:24 +00003460 unsigned RtReg;
3461 int64_t ImmValue;
3462
3463 const MCOperand &RtOp = Inst.getOperand(2);
3464 assert((RtOp.isReg() || RtOp.isImm()) &&
3465 "expected register or immediate operand kind");
3466 if (RtOp.isReg())
3467 RtReg = RtOp.getReg();
3468 else
3469 ImmValue = RtOp.getImm();
3470
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003471 unsigned DivOp;
3472 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003473 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003474
3475 if (IsMips64) {
3476 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3477 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003478 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003479 } else {
3480 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3481 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003482 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003483 }
3484
3485 bool UseTraps = useTraps();
3486
Simon Dardis12850ee2017-01-31 10:49:24 +00003487 if (RtOp.isImm()) {
3488 unsigned ATReg = getATReg(IDLoc);
3489 if (!ATReg)
3490 return true;
3491
3492 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003493 if (UseTraps)
3494 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3495 else
3496 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3497 return false;
3498 }
3499
3500 if (ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003501 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003502 return false;
3503 } else if (Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003504 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003505 return false;
3506 } else {
3507 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
3508 false, Inst.getLoc(), Out, STI))
3509 return true;
3510 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
3511 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
3512 return false;
3513 }
3514 return true;
3515 }
3516
Simon Dardis509da1a2017-02-13 16:06:48 +00003517 // If the macro expansion of (d)div(u) would always trap or break, insert
3518 // the trap/break and exit. This gives a different result to GAS. GAS has
3519 // an inconsistency/missed optimization in that not all cases are handled
3520 // equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003521 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003522 if (UseTraps) {
3523 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003524 return false;
3525 }
Simon Dardis509da1a2017-02-13 16:06:48 +00003526 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3527 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003528 }
3529
Simon Dardis509da1a2017-02-13 16:06:48 +00003530 // Temporary label for first branch traget
3531 MCContext &Context = TOut.getStreamer().getContext();
3532 MCSymbol *BrTarget;
3533 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003534
3535 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003536 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003537 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003538 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00003539 BrTarget = Context.createTempSymbol();
3540 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
3541 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003542 }
3543
Daniel Sandersa736b372016-04-29 13:33:12 +00003544 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003545
3546 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003547 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003548
3549 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003550 if (!UseTraps)
3551 TOut.getStreamer().EmitLabel(BrTarget);
3552
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003553 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003554 return false;
3555 }
3556
3557 unsigned ATReg = getATReg(IDLoc);
3558 if (!ATReg)
3559 return true;
3560
Simon Dardis509da1a2017-02-13 16:06:48 +00003561 if (!UseTraps)
3562 TOut.getStreamer().EmitLabel(BrTarget);
3563
Daniel Sandersa736b372016-04-29 13:33:12 +00003564 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00003565
3566 // Temporary label for the second branch target.
3567 MCSymbol *BrTargetEnd = Context.createTempSymbol();
3568 MCOperand LabelOpEnd =
3569 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
3570
3571 // Branch to the mflo instruction.
3572 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
3573
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003574 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003575 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3576 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003577 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00003578 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003579 }
3580
3581 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003582 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003583 else {
3584 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00003585 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00003586 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3587 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003588 }
Simon Dardis509da1a2017-02-13 16:06:48 +00003589
3590 TOut.getStreamer().EmitLabel(BrTargetEnd);
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003591 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003592 return false;
3593}
3594
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003595bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003596 SMLoc IDLoc, MCStreamer &Out,
3597 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003598 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003599
3600 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3601 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3602 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3603
3604 unsigned FirstReg = Inst.getOperand(0).getReg();
3605 unsigned SecondReg = Inst.getOperand(1).getReg();
3606 unsigned ThirdReg = Inst.getOperand(2).getReg();
3607
3608 if (hasMips1() && !hasMips2()) {
3609 unsigned ATReg = getATReg(IDLoc);
3610 if (!ATReg)
3611 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003612 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3613 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3614 TOut.emitNop(IDLoc, STI);
3615 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3616 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3617 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3618 TOut.emitNop(IDLoc, STI);
3619 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3620 : Mips::CVT_W_S,
3621 FirstReg, SecondReg, IDLoc, STI);
3622 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3623 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003624 return false;
3625 }
3626
Daniel Sandersa736b372016-04-29 13:33:12 +00003627 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3628 : Mips::TRUNC_W_S,
3629 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003630
3631 return false;
3632}
3633
Daniel Sanders6394ee52015-10-15 14:52:58 +00003634bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003635 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003636 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003637 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003638 }
3639
Toma Tabacud88d79c2015-06-23 14:39:42 +00003640 const MCOperand &DstRegOp = Inst.getOperand(0);
3641 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003642 const MCOperand &SrcRegOp = Inst.getOperand(1);
3643 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003644 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3645 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3646
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003647 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00003648 unsigned DstReg = DstRegOp.getReg();
3649 unsigned SrcReg = SrcRegOp.getReg();
3650 int64_t OffsetValue = OffsetImmOp.getImm();
3651
3652 // NOTE: We always need AT for ULHU, as it is always used as the source
3653 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003654 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003655 unsigned ATReg = getATReg(IDLoc);
3656 if (!ATReg)
3657 return true;
3658
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003659 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
3660 if (IsLargeOffset) {
3661 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
3662 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003663 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00003664 }
3665
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003666 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
3667 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
3668 if (isLittle())
3669 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003670
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003671 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
3672 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00003673
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003674 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
3675 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00003676
Daniel Sandersa736b372016-04-29 13:33:12 +00003677 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003678 FirstOffset, IDLoc, STI);
3679 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00003680 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00003681 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003682
3683 return false;
3684}
3685
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003686bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003687 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003688 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003689 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003690 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003691
3692 const MCOperand &DstRegOp = Inst.getOperand(0);
3693 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003694 const MCOperand &SrcRegOp = Inst.getOperand(1);
3695 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003696 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3697 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3698
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003699 MipsTargetStreamer &TOut = getTargetStreamer();
3700 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003701 unsigned SrcReg = SrcRegOp.getReg();
3702 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003703
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003704 warnIfNoMacro(IDLoc);
3705 unsigned ATReg = getATReg(IDLoc);
3706 if (!ATReg)
3707 return true;
3708
3709 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
3710 if (IsLargeOffset) {
3711 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
3712 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003713 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003714 }
3715
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003716 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
3717 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
3718 if (isLittle())
3719 std::swap(FirstOffset, SecondOffset);
3720
3721 if (IsLargeOffset) {
3722 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
3723 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
3724 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
3725 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
3726 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
3727 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003728 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003729 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
3730 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
3731 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003732 }
3733
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003734 return false;
3735}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003736
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003737bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3738 const MCSubtargetInfo *STI) {
3739 if (hasMips32r6() || hasMips64r6()) {
3740 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3741 }
3742
3743 const MCOperand &DstRegOp = Inst.getOperand(0);
3744 assert(DstRegOp.isReg() && "expected register operand kind");
3745 const MCOperand &SrcRegOp = Inst.getOperand(1);
3746 assert(SrcRegOp.isReg() && "expected register operand kind");
3747 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3748 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3749
3750 MipsTargetStreamer &TOut = getTargetStreamer();
3751 unsigned DstReg = DstRegOp.getReg();
3752 unsigned SrcReg = SrcRegOp.getReg();
3753 int64_t OffsetValue = OffsetImmOp.getImm();
3754
3755 // Compute left/right load/store offsets.
3756 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
3757 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
3758 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
3759 if (isLittle())
3760 std::swap(LxlOffset, LxrOffset);
3761
3762 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
3763 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
3764 unsigned TmpReg = SrcReg;
3765 if (IsLargeOffset || DoMove) {
3766 warnIfNoMacro(IDLoc);
3767 TmpReg = getATReg(IDLoc);
3768 if (!TmpReg)
3769 return true;
3770 }
3771
3772 if (IsLargeOffset) {
3773 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
3774 IDLoc, Out, STI))
3775 return true;
3776 }
3777
3778 if (DoMove)
3779 std::swap(DstReg, TmpReg);
3780
3781 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
3782 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
3783 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
3784 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
3785
3786 if (DoMove)
3787 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003788
3789 return false;
3790}
3791
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003792bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003793 MCStreamer &Out,
3794 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003795 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003796
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003797 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3798 assert(Inst.getOperand(0).isReg() &&
3799 Inst.getOperand(1).isReg() &&
3800 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003801
3802 unsigned ATReg = Mips::NoRegister;
3803 unsigned FinalDstReg = Mips::NoRegister;
3804 unsigned DstReg = Inst.getOperand(0).getReg();
3805 unsigned SrcReg = Inst.getOperand(1).getReg();
3806 int64_t ImmValue = Inst.getOperand(2).getImm();
3807
3808 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3809
3810 unsigned FinalOpcode = Inst.getOpcode();
3811
3812 if (DstReg == SrcReg) {
3813 ATReg = getATReg(Inst.getLoc());
3814 if (!ATReg)
3815 return true;
3816 FinalDstReg = DstReg;
3817 DstReg = ATReg;
3818 }
3819
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003820 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003821 switch (FinalOpcode) {
3822 default:
3823 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00003824 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003825 FinalOpcode = Mips::ADD;
3826 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00003827 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003828 FinalOpcode = Mips::ADDu;
3829 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00003830 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003831 FinalOpcode = Mips::AND;
3832 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00003833 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003834 FinalOpcode = Mips::NOR;
3835 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00003836 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003837 FinalOpcode = Mips::OR;
3838 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00003839 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003840 FinalOpcode = Mips::SLT;
3841 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00003842 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003843 FinalOpcode = Mips::SLTu;
3844 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00003845 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003846 FinalOpcode = Mips::XOR;
3847 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00003848 case Mips::ADDi_MM:
3849 FinalOpcode = Mips::ADD_MM;
3850 break;
3851 case Mips::ADDiu_MM:
3852 FinalOpcode = Mips::ADDu_MM;
3853 break;
3854 case Mips::ANDi_MM:
3855 FinalOpcode = Mips::AND_MM;
3856 break;
3857 case Mips::ORi_MM:
3858 FinalOpcode = Mips::OR_MM;
3859 break;
3860 case Mips::SLTi_MM:
3861 FinalOpcode = Mips::SLT_MM;
3862 break;
3863 case Mips::SLTiu_MM:
3864 FinalOpcode = Mips::SLTu_MM;
3865 break;
3866 case Mips::XORi_MM:
3867 FinalOpcode = Mips::XOR_MM;
3868 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003869 }
3870
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003871 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003872 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003873 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003874 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003875 return false;
3876 }
3877 return true;
3878}
3879
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003880bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3881 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003882 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003883 unsigned ATReg = Mips::NoRegister;
3884 unsigned DReg = Inst.getOperand(0).getReg();
3885 unsigned SReg = Inst.getOperand(1).getReg();
3886 unsigned TReg = Inst.getOperand(2).getReg();
3887 unsigned TmpReg = DReg;
3888
3889 unsigned FirstShift = Mips::NOP;
3890 unsigned SecondShift = Mips::NOP;
3891
3892 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003893 if (DReg == SReg) {
3894 TmpReg = getATReg(Inst.getLoc());
3895 if (!TmpReg)
3896 return true;
3897 }
3898
3899 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003900 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3901 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003902 return false;
3903 }
3904
3905 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003906 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003907 return false;
3908 }
3909
3910 return true;
3911 }
3912
3913 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003914 switch (Inst.getOpcode()) {
3915 default:
3916 llvm_unreachable("unexpected instruction opcode");
3917 case Mips::ROL:
3918 FirstShift = Mips::SRLV;
3919 SecondShift = Mips::SLLV;
3920 break;
3921 case Mips::ROR:
3922 FirstShift = Mips::SLLV;
3923 SecondShift = Mips::SRLV;
3924 break;
3925 }
3926
3927 ATReg = getATReg(Inst.getLoc());
3928 if (!ATReg)
3929 return true;
3930
Daniel Sandersa736b372016-04-29 13:33:12 +00003931 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3932 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3933 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3934 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003935
3936 return false;
3937 }
3938
3939 return true;
3940}
3941
3942bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003943 MCStreamer &Out,
3944 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003945 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003946 unsigned ATReg = Mips::NoRegister;
3947 unsigned DReg = Inst.getOperand(0).getReg();
3948 unsigned SReg = Inst.getOperand(1).getReg();
3949 int64_t ImmValue = Inst.getOperand(2).getImm();
3950
3951 unsigned FirstShift = Mips::NOP;
3952 unsigned SecondShift = Mips::NOP;
3953
3954 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003955 if (Inst.getOpcode() == Mips::ROLImm) {
3956 uint64_t MaxShift = 32;
3957 uint64_t ShiftValue = ImmValue;
3958 if (ImmValue != 0)
3959 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003960 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003961 return false;
3962 }
3963
3964 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003965 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003966 return false;
3967 }
3968
3969 return true;
3970 }
3971
3972 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003973 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003974 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003975 return false;
3976 }
3977
3978 switch (Inst.getOpcode()) {
3979 default:
3980 llvm_unreachable("unexpected instruction opcode");
3981 case Mips::ROLImm:
3982 FirstShift = Mips::SLL;
3983 SecondShift = Mips::SRL;
3984 break;
3985 case Mips::RORImm:
3986 FirstShift = Mips::SRL;
3987 SecondShift = Mips::SLL;
3988 break;
3989 }
3990
3991 ATReg = getATReg(Inst.getLoc());
3992 if (!ATReg)
3993 return true;
3994
Daniel Sandersa736b372016-04-29 13:33:12 +00003995 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3996 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3997 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003998
3999 return false;
4000 }
4001
4002 return true;
4003}
4004
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004005bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4006 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004007 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004008 unsigned ATReg = Mips::NoRegister;
4009 unsigned DReg = Inst.getOperand(0).getReg();
4010 unsigned SReg = Inst.getOperand(1).getReg();
4011 unsigned TReg = Inst.getOperand(2).getReg();
4012 unsigned TmpReg = DReg;
4013
4014 unsigned FirstShift = Mips::NOP;
4015 unsigned SecondShift = Mips::NOP;
4016
4017 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004018 if (TmpReg == SReg) {
4019 TmpReg = getATReg(Inst.getLoc());
4020 if (!TmpReg)
4021 return true;
4022 }
4023
4024 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004025 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4026 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004027 return false;
4028 }
4029
4030 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004031 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004032 return false;
4033 }
4034
4035 return true;
4036 }
4037
4038 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004039 switch (Inst.getOpcode()) {
4040 default:
4041 llvm_unreachable("unexpected instruction opcode");
4042 case Mips::DROL:
4043 FirstShift = Mips::DSRLV;
4044 SecondShift = Mips::DSLLV;
4045 break;
4046 case Mips::DROR:
4047 FirstShift = Mips::DSLLV;
4048 SecondShift = Mips::DSRLV;
4049 break;
4050 }
4051
4052 ATReg = getATReg(Inst.getLoc());
4053 if (!ATReg)
4054 return true;
4055
Daniel Sandersa736b372016-04-29 13:33:12 +00004056 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4057 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4058 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4059 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004060
4061 return false;
4062 }
4063
4064 return true;
4065}
4066
4067bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004068 MCStreamer &Out,
4069 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004070 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004071 unsigned ATReg = Mips::NoRegister;
4072 unsigned DReg = Inst.getOperand(0).getReg();
4073 unsigned SReg = Inst.getOperand(1).getReg();
4074 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4075
4076 unsigned FirstShift = Mips::NOP;
4077 unsigned SecondShift = Mips::NOP;
4078
4079 MCInst TmpInst;
4080
4081 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004082 unsigned FinalOpcode = Mips::NOP;
4083 if (ImmValue == 0)
4084 FinalOpcode = Mips::DROTR;
4085 else if (ImmValue % 32 == 0)
4086 FinalOpcode = Mips::DROTR32;
4087 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4088 if (Inst.getOpcode() == Mips::DROLImm)
4089 FinalOpcode = Mips::DROTR32;
4090 else
4091 FinalOpcode = Mips::DROTR;
4092 } else if (ImmValue >= 33) {
4093 if (Inst.getOpcode() == Mips::DROLImm)
4094 FinalOpcode = Mips::DROTR;
4095 else
4096 FinalOpcode = Mips::DROTR32;
4097 }
4098
4099 uint64_t ShiftValue = ImmValue % 32;
4100 if (Inst.getOpcode() == Mips::DROLImm)
4101 ShiftValue = (32 - ImmValue % 32) % 32;
4102
Daniel Sandersa736b372016-04-29 13:33:12 +00004103 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004104
4105 return false;
4106 }
4107
4108 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004109 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004110 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004111 return false;
4112 }
4113
4114 switch (Inst.getOpcode()) {
4115 default:
4116 llvm_unreachable("unexpected instruction opcode");
4117 case Mips::DROLImm:
4118 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4119 FirstShift = Mips::DSLL;
4120 SecondShift = Mips::DSRL32;
4121 }
4122 if (ImmValue == 32) {
4123 FirstShift = Mips::DSLL32;
4124 SecondShift = Mips::DSRL32;
4125 }
4126 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4127 FirstShift = Mips::DSLL32;
4128 SecondShift = Mips::DSRL;
4129 }
4130 break;
4131 case Mips::DRORImm:
4132 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4133 FirstShift = Mips::DSRL;
4134 SecondShift = Mips::DSLL32;
4135 }
4136 if (ImmValue == 32) {
4137 FirstShift = Mips::DSRL32;
4138 SecondShift = Mips::DSLL32;
4139 }
4140 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4141 FirstShift = Mips::DSRL32;
4142 SecondShift = Mips::DSLL;
4143 }
4144 break;
4145 }
4146
4147 ATReg = getATReg(Inst.getLoc());
4148 if (!ATReg)
4149 return true;
4150
Daniel Sandersa736b372016-04-29 13:33:12 +00004151 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4152 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4153 Inst.getLoc(), STI);
4154 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004155
4156 return false;
4157 }
4158
4159 return true;
4160}
4161
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004162bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4163 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004164 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004165 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4166 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4167
Daniel Sandersa736b372016-04-29 13:33:12 +00004168 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004169 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004170 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004171 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004172 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4173 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004174
4175 return false;
4176}
4177
Simon Dardis3c82a642017-02-08 16:25:05 +00004178bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4179 const MCSubtargetInfo *STI) {
4180 MipsTargetStreamer &TOut = getTargetStreamer();
4181 unsigned ATReg = Mips::NoRegister;
4182 unsigned DstReg = Inst.getOperand(0).getReg();
4183 unsigned SrcReg = Inst.getOperand(1).getReg();
4184 int32_t ImmValue = Inst.getOperand(2).getImm();
4185
4186 ATReg = getATReg(IDLoc);
4187 if (!ATReg)
4188 return true;
4189
4190 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI);
4191
4192 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4193 SrcReg, ATReg, IDLoc, STI);
4194
4195 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4196
4197 return false;
4198}
4199
4200bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4201 const MCSubtargetInfo *STI) {
4202 MipsTargetStreamer &TOut = getTargetStreamer();
4203 unsigned ATReg = Mips::NoRegister;
4204 unsigned DstReg = Inst.getOperand(0).getReg();
4205 unsigned SrcReg = Inst.getOperand(1).getReg();
4206 unsigned TmpReg = Inst.getOperand(2).getReg();
4207
4208 ATReg = getATReg(Inst.getLoc());
4209 if (!ATReg)
4210 return true;
4211
4212 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4213 SrcReg, TmpReg, IDLoc, STI);
4214
4215 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4216
4217 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4218 DstReg, DstReg, 0x1F, IDLoc, STI);
4219
4220 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4221
4222 if (useTraps()) {
4223 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4224 } else {
4225 MCContext & Context = TOut.getStreamer().getContext();
4226 MCSymbol * BrTarget = Context.createTempSymbol();
4227 MCOperand LabelOp =
4228 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4229
4230 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4231 if (AssemblerOptions.back()->isReorder())
4232 TOut.emitNop(IDLoc, STI);
4233 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4234
4235 TOut.getStreamer().EmitLabel(BrTarget);
4236 }
4237 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4238
4239 return false;
4240}
4241
4242bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4243 const MCSubtargetInfo *STI) {
4244 MipsTargetStreamer &TOut = getTargetStreamer();
4245 unsigned ATReg = Mips::NoRegister;
4246 unsigned DstReg = Inst.getOperand(0).getReg();
4247 unsigned SrcReg = Inst.getOperand(1).getReg();
4248 unsigned TmpReg = Inst.getOperand(2).getReg();
4249
4250 ATReg = getATReg(IDLoc);
4251 if (!ATReg)
4252 return true;
4253
4254 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4255 SrcReg, TmpReg, IDLoc, STI);
4256
4257 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4258 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4259 if (useTraps()) {
4260 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4261 } else {
4262 MCContext & Context = TOut.getStreamer().getContext();
4263 MCSymbol * BrTarget = Context.createTempSymbol();
4264 MCOperand LabelOp =
4265 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4266
4267 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4268 if (AssemblerOptions.back()->isReorder())
4269 TOut.emitNop(IDLoc, STI);
4270 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4271
4272 TOut.getStreamer().EmitLabel(BrTarget);
4273 }
4274
4275 return false;
4276}
4277
4278bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4279 const MCSubtargetInfo *STI) {
4280 MipsTargetStreamer &TOut = getTargetStreamer();
4281 unsigned DstReg = Inst.getOperand(0).getReg();
4282 unsigned SrcReg = Inst.getOperand(1).getReg();
4283 unsigned TmpReg = Inst.getOperand(2).getReg();
4284
4285 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4286 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4287
4288 return false;
4289}
4290
Simon Dardisaff4d142016-10-18 14:28:00 +00004291static unsigned nextReg(unsigned Reg) {
4292 switch (Reg) {
4293 case Mips::ZERO: return Mips::AT;
4294 case Mips::AT: return Mips::V0;
4295 case Mips::V0: return Mips::V1;
4296 case Mips::V1: return Mips::A0;
4297 case Mips::A0: return Mips::A1;
4298 case Mips::A1: return Mips::A2;
4299 case Mips::A2: return Mips::A3;
4300 case Mips::A3: return Mips::T0;
4301 case Mips::T0: return Mips::T1;
4302 case Mips::T1: return Mips::T2;
4303 case Mips::T2: return Mips::T3;
4304 case Mips::T3: return Mips::T4;
4305 case Mips::T4: return Mips::T5;
4306 case Mips::T5: return Mips::T6;
4307 case Mips::T6: return Mips::T7;
4308 case Mips::T7: return Mips::S0;
4309 case Mips::S0: return Mips::S1;
4310 case Mips::S1: return Mips::S2;
4311 case Mips::S2: return Mips::S3;
4312 case Mips::S3: return Mips::S4;
4313 case Mips::S4: return Mips::S5;
4314 case Mips::S5: return Mips::S6;
4315 case Mips::S6: return Mips::S7;
4316 case Mips::S7: return Mips::T8;
4317 case Mips::T8: return Mips::T9;
4318 case Mips::T9: return Mips::K0;
4319 case Mips::K0: return Mips::K1;
4320 case Mips::K1: return Mips::GP;
4321 case Mips::GP: return Mips::SP;
4322 case Mips::SP: return Mips::FP;
4323 case Mips::FP: return Mips::RA;
4324 case Mips::RA: return Mips::ZERO;
4325 default: return 0;
4326 }
4327
4328}
4329
4330// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4331// lw $<reg+1>>, offset+4($reg2)'
4332// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4333// sw $<reg+1>>, offset+4($reg2)'
4334// for O32.
4335bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4336 MCStreamer &Out,
4337 const MCSubtargetInfo *STI,
4338 bool IsLoad) {
4339 if (!isABI_O32())
4340 return true;
4341
4342 warnIfNoMacro(IDLoc);
4343
4344 MipsTargetStreamer &TOut = getTargetStreamer();
4345 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4346 unsigned FirstReg = Inst.getOperand(0).getReg();
4347 unsigned SecondReg = nextReg(FirstReg);
4348 unsigned BaseReg = Inst.getOperand(1).getReg();
4349 if (!SecondReg)
4350 return true;
4351
4352 warnIfRegIndexIsAT(FirstReg, IDLoc);
4353
4354 assert(Inst.getOperand(2).isImm() &&
4355 "Offset for load macro is not immediate!");
4356
4357 MCOperand &FirstOffset = Inst.getOperand(2);
4358 signed NextOffset = FirstOffset.getImm() + 4;
4359 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4360
4361 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4362 return true;
4363
4364 // For loads, clobber the base register with the second load instead of the
4365 // first if the BaseReg == FirstReg.
4366 if (FirstReg != BaseReg || !IsLoad) {
4367 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4368 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4369 } else {
4370 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4371 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4372 }
4373
4374 return false;
4375}
4376
Simon Dardis43115a12016-11-21 20:30:41 +00004377bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4378 const MCSubtargetInfo *STI) {
4379
4380 warnIfNoMacro(IDLoc);
4381 MipsTargetStreamer &TOut = getTargetStreamer();
4382
4383 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4384 Inst.getOperand(2).getReg() != Mips::ZERO) {
4385 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4386 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4387 IDLoc, STI);
4388 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4389 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4390 return false;
4391 }
4392
4393 unsigned Reg = 0;
4394 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4395 Reg = Inst.getOperand(2).getReg();
4396 } else {
4397 Reg = Inst.getOperand(1).getReg();
4398 }
4399 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4400 return false;
4401}
4402
4403bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4404 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004405 warnIfNoMacro(IDLoc);
4406 MipsTargetStreamer &TOut = getTargetStreamer();
4407
4408 unsigned Opc;
4409 int64_t Imm = Inst.getOperand(2).getImm();
4410 unsigned Reg = Inst.getOperand(1).getReg();
4411
4412 if (Imm == 0) {
4413 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4414 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4415 return false;
4416 } else {
4417
4418 if (Reg == Mips::ZERO) {
4419 Warning(IDLoc, "comparison is always false");
4420 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4421 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4422 return false;
4423 }
4424
4425 if (Imm > -0x8000 && Imm < 0) {
4426 Imm = -Imm;
4427 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4428 } else {
4429 Opc = Mips::XORi;
4430 }
4431 }
4432 if (!isUInt<16>(Imm)) {
4433 unsigned ATReg = getATReg(IDLoc);
4434 if (!ATReg)
4435 return true;
4436
4437 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4438 Out, STI))
4439 return true;
4440
4441 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4442 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4443 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4444 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4445 return false;
4446 }
4447
4448 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4449 Imm, IDLoc, STI);
4450 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4451 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4452 return false;
4453}
4454
Daniel Sandersc5537422016-07-27 13:49:44 +00004455unsigned
4456MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
4457 const OperandVector &Operands) {
4458 switch (Inst.getOpcode()) {
4459 default:
4460 return Match_Success;
4461 case Mips::DATI:
4462 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00004463 case Mips::DATI_MM64R6:
4464 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00004465 if (static_cast<MipsOperand &>(*Operands[1])
4466 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
4467 return Match_Success;
4468 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00004469 }
4470}
Simon Dardis730fdb72017-01-16 13:55:58 +00004471
Matheus Almeida595fcab2014-06-11 15:05:56 +00004472unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00004473 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00004474 // As described by the MIPSR6 spec, daui must not use the zero operand for
4475 // its source operand.
4476 case Mips::DAUI:
4477 case Mips::DAUI_MM64R6:
4478 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4479 Inst.getOperand(1).getReg() == Mips::ZERO_64)
4480 return Match_RequiresNoZeroRegister;
4481 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00004482 // As described by the Mips32r2 spec, the registers Rd and Rs for
4483 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00004484 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00004485 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00004486 case Mips::JALR_HB:
4487 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00004488 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00004489 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4490 return Match_RequiresDifferentSrcAndDst;
4491 return Match_Success;
4492 case Mips::LWP_MM:
4493 case Mips::LWP_MMR6:
4494 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
4495 return Match_RequiresDifferentSrcAndDst;
4496 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00004497 case Mips::SYNC:
4498 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
4499 return Match_NonZeroOperandForSync;
4500 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004501 // As described the MIPSR6 spec, the compact branches that compare registers
4502 // must:
4503 // a) Not use the zero register.
4504 // b) Not use the same register twice.
4505 // c) rs < rt for bnec, beqc.
4506 // NB: For this case, the encoding will swap the operands as their
4507 // ordering doesn't matter. GAS performs this transformation too.
4508 // Hence, that constraint does not have to be enforced.
4509 //
4510 // The compact branches that branch iff the signed addition of two registers
4511 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
4512 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004513 case Mips::BLEZC: case Mips::BLEZC_MMR6:
4514 case Mips::BGEZC: case Mips::BGEZC_MMR6:
4515 case Mips::BGTZC: case Mips::BGTZC_MMR6:
4516 case Mips::BLTZC: case Mips::BLTZC_MMR6:
4517 case Mips::BEQZC: case Mips::BEQZC_MMR6:
4518 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004519 case Mips::BLEZC64:
4520 case Mips::BGEZC64:
4521 case Mips::BGTZC64:
4522 case Mips::BLTZC64:
4523 case Mips::BEQZC64:
4524 case Mips::BNEZC64:
4525 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4526 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004527 return Match_RequiresNoZeroRegister;
4528 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004529 case Mips::BGEC: case Mips::BGEC_MMR6:
4530 case Mips::BLTC: case Mips::BLTC_MMR6:
4531 case Mips::BGEUC: case Mips::BGEUC_MMR6:
4532 case Mips::BLTUC: case Mips::BLTUC_MMR6:
4533 case Mips::BEQC: case Mips::BEQC_MMR6:
4534 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004535 case Mips::BGEC64:
4536 case Mips::BLTC64:
4537 case Mips::BGEUC64:
4538 case Mips::BLTUC64:
4539 case Mips::BEQC64:
4540 case Mips::BNEC64:
4541 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4542 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004543 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00004544 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4545 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004546 return Match_RequiresNoZeroRegister;
4547 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4548 return Match_RequiresDifferentOperands;
4549 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004550 }
Simon Dardis730fdb72017-01-16 13:55:58 +00004551
4552 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
4553 if ((TSFlags & MipsII::HasFCCRegOperand) &&
4554 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
4555 return Match_NoFCCRegisterForCurrentISA;
4556
4557 return Match_Success;
4558
Matheus Almeida595fcab2014-06-11 15:05:56 +00004559}
4560
Daniel Sanders52da7af2015-11-06 12:11:03 +00004561static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
4562 uint64_t ErrorInfo) {
4563 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
4564 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
4565 if (ErrorLoc == SMLoc())
4566 return Loc;
4567 return ErrorLoc;
4568 }
4569 return Loc;
4570}
4571
David Blaikie960ea3f2014-06-08 16:18:35 +00004572bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4573 OperandVector &Operands,
4574 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004575 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00004576 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004577 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00004578 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004579 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00004580
4581 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004582 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004583 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00004584 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004585 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00004586 case Match_MissingFeature:
4587 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4588 return true;
4589 case Match_InvalidOperand: {
4590 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00004591 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004592 if (ErrorInfo >= Operands.size())
4593 return Error(IDLoc, "too few operands for instruction");
4594
Daniel Sanders52da7af2015-11-06 12:11:03 +00004595 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00004596 if (ErrorLoc == SMLoc())
4597 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00004598 }
4599
4600 return Error(ErrorLoc, "invalid operand for instruction");
4601 }
Simon Dardisc4463c92016-10-18 14:42:13 +00004602 case Match_NonZeroOperandForSync:
4603 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00004604 case Match_MnemonicFail:
4605 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00004606 case Match_RequiresDifferentSrcAndDst:
4607 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00004608 case Match_RequiresDifferentOperands:
4609 return Error(IDLoc, "registers must be different");
4610 case Match_RequiresNoZeroRegister:
4611 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00004612 case Match_RequiresSameSrcAndDst:
4613 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00004614 case Match_NoFCCRegisterForCurrentISA:
4615 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4616 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00004617 case Match_Immz:
4618 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004619 case Match_UImm1_0:
4620 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4621 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00004622 case Match_UImm2_0:
4623 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4624 "expected 2-bit unsigned immediate");
4625 case Match_UImm2_1:
4626 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4627 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00004628 case Match_UImm3_0:
4629 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4630 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004631 case Match_UImm4_0:
4632 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4633 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00004634 case Match_SImm4_0:
4635 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4636 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004637 case Match_UImm5_0:
4638 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4639 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00004640 case Match_SImm5_0:
4641 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4642 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004643 case Match_UImm5_1:
4644 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4645 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004646 case Match_UImm5_32:
4647 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4648 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004649 case Match_UImm5_33:
4650 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4651 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004652 case Match_UImm5_0_Report_UImm6:
4653 // This is used on UImm5 operands that have a corresponding UImm5_32
4654 // operand to avoid confusing the user.
4655 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4656 "expected 6-bit unsigned immediate");
4657 case Match_UImm5_Lsl2:
4658 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4659 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00004660 case Match_UImmRange2_64:
4661 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4662 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00004663 case Match_UImm6_0:
4664 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4665 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00004666 case Match_UImm6_Lsl2:
4667 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4668 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00004669 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00004670 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4671 "expected 6-bit signed immediate");
4672 case Match_UImm7_0:
4673 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4674 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00004675 case Match_UImm7_N1:
4676 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4677 "expected immediate in range -1 .. 126");
4678 case Match_SImm7_Lsl2:
4679 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4680 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00004681 case Match_UImm8_0:
4682 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4683 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00004684 case Match_UImm10_0:
4685 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4686 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00004687 case Match_SImm10_0:
4688 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4689 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00004690 case Match_SImm11_0:
4691 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4692 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00004693 case Match_UImm16:
4694 case Match_UImm16_Relaxed:
4695 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4696 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004697 case Match_SImm16:
4698 case Match_SImm16_Relaxed:
4699 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4700 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00004701 case Match_SImm19_Lsl2:
4702 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4703 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00004704 case Match_UImm20_0:
4705 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4706 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00004707 case Match_UImm26_0:
4708 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4709 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00004710 case Match_SImm32:
4711 case Match_SImm32_Relaxed:
4712 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4713 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00004714 case Match_UImm32_Coerced:
4715 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4716 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00004717 case Match_MemSImm9:
4718 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4719 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00004720 case Match_MemSImm10:
4721 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4722 "expected memory with 10-bit signed offset");
4723 case Match_MemSImm10Lsl1:
4724 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4725 "expected memory with 11-bit signed offset and multiple of 2");
4726 case Match_MemSImm10Lsl2:
4727 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4728 "expected memory with 12-bit signed offset and multiple of 4");
4729 case Match_MemSImm10Lsl3:
4730 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4731 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00004732 case Match_MemSImm11:
4733 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4734 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00004735 case Match_MemSImm12:
4736 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4737 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004738 case Match_MemSImm16:
4739 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4740 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00004741 }
Craig Topper589ceee2015-01-03 08:16:34 +00004742
4743 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00004744}
4745
Toma Tabacud9d344b2015-04-27 14:05:04 +00004746void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
4747 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
4748 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
4749 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004750}
4751
Toma Tabacu81496c12015-05-20 08:54:45 +00004752void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
4753 if (!AssemblerOptions.back()->isMacro())
4754 Warning(Loc, "macro instruction expanded into multiple instructions");
4755}
4756
Daniel Sandersef638fe2014-10-03 15:37:37 +00004757void
4758MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
4759 SMRange Range, bool ShowColors) {
4760 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00004761 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00004762 ShowColors);
4763}
4764
Jack Carter1ac53222013-02-20 23:11:17 +00004765int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004766 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004767
Vladimir Medic4c299852013-11-06 11:27:05 +00004768 CC = StringSwitch<unsigned>(Name)
4769 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004770 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00004771 .Case("a0", 4)
4772 .Case("a1", 5)
4773 .Case("a2", 6)
4774 .Case("a3", 7)
4775 .Case("v0", 2)
4776 .Case("v1", 3)
4777 .Case("s0", 16)
4778 .Case("s1", 17)
4779 .Case("s2", 18)
4780 .Case("s3", 19)
4781 .Case("s4", 20)
4782 .Case("s5", 21)
4783 .Case("s6", 22)
4784 .Case("s7", 23)
4785 .Case("k0", 26)
4786 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004787 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00004788 .Case("sp", 29)
4789 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004790 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00004791 .Case("ra", 31)
4792 .Case("t0", 8)
4793 .Case("t1", 9)
4794 .Case("t2", 10)
4795 .Case("t3", 11)
4796 .Case("t4", 12)
4797 .Case("t5", 13)
4798 .Case("t6", 14)
4799 .Case("t7", 15)
4800 .Case("t8", 24)
4801 .Case("t9", 25)
4802 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004803
Toma Tabacufda445c2014-09-15 15:33:01 +00004804 if (!(isABI_N32() || isABI_N64()))
4805 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004806
Daniel Sandersef638fe2014-10-03 15:37:37 +00004807 if (12 <= CC && CC <= 15) {
4808 // Name is one of t4-t7
4809 AsmToken RegTok = getLexer().peekTok();
4810 SMRange RegRange = RegTok.getLocRange();
4811
4812 StringRef FixedName = StringSwitch<StringRef>(Name)
4813 .Case("t4", "t0")
4814 .Case("t5", "t1")
4815 .Case("t6", "t2")
4816 .Case("t7", "t3")
4817 .Default("");
4818 assert(FixedName != "" && "Register name is not one of t4-t7.");
4819
4820 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
4821 "Did you mean $" + FixedName + "?", RegRange);
4822 }
4823
Toma Tabacufda445c2014-09-15 15:33:01 +00004824 // Although SGI documentation just cuts out t0-t3 for n32/n64,
4825 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
4826 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
4827 if (8 <= CC && CC <= 11)
4828 CC += 4;
4829
4830 if (CC == -1)
4831 CC = StringSwitch<unsigned>(Name)
4832 .Case("a4", 8)
4833 .Case("a5", 9)
4834 .Case("a6", 10)
4835 .Case("a7", 11)
4836 .Case("kt0", 26)
4837 .Case("kt1", 27)
4838 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004839
4840 return CC;
4841}
Jack Carterd0bd6422013-04-18 00:41:53 +00004842
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004843int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
4844 int CC;
4845
4846 CC = StringSwitch<unsigned>(Name)
4847 .Case("hwr_cpunum", 0)
4848 .Case("hwr_synci_step", 1)
4849 .Case("hwr_cc", 2)
4850 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00004851 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004852 .Default(-1);
4853
4854 return CC;
4855}
4856
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004857int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00004858 if (Name[0] == 'f') {
4859 StringRef NumString = Name.substr(1);
4860 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004861 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004862 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004863 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00004864 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004865 return IntVal;
4866 }
4867 return -1;
4868}
Jack Cartera63b16a2012-09-07 00:23:42 +00004869
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004870int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004871 if (Name.startswith("fcc")) {
4872 StringRef NumString = Name.substr(3);
4873 unsigned IntVal;
4874 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004875 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004876 if (IntVal > 7) // There are only 8 fcc registers.
4877 return -1;
4878 return IntVal;
4879 }
4880 return -1;
4881}
4882
4883int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00004884 if (Name.startswith("ac")) {
4885 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004886 unsigned IntVal;
4887 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004888 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004889 if (IntVal > 3) // There are only 3 acc registers.
4890 return -1;
4891 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00004892 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004893 return -1;
4894}
Jack Carterd0bd6422013-04-18 00:41:53 +00004895
Jack Carter5dc8ac92013-09-25 23:50:44 +00004896int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
4897 unsigned IntVal;
4898
4899 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
4900 return -1;
4901
4902 if (IntVal > 31)
4903 return -1;
4904
4905 return IntVal;
4906}
4907
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004908int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
4909 int CC;
4910
4911 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00004912 .Case("msair", 0)
4913 .Case("msacsr", 1)
4914 .Case("msaaccess", 2)
4915 .Case("msasave", 3)
4916 .Case("msamodify", 4)
4917 .Case("msarequest", 5)
4918 .Case("msamap", 6)
4919 .Case("msaunmap", 7)
4920 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004921
4922 return CC;
4923}
4924
Simon Dardis3aa8a902017-02-06 12:43:46 +00004925bool MipsAsmParser::canUseATReg() {
4926 return AssemblerOptions.back()->getATRegIndex() != 0;
4927}
4928
Toma Tabacu89a712b2015-04-15 10:48:56 +00004929unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004930 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004931 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004932 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004933 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004934 return 0;
4935 }
4936 unsigned AT = getReg(
4937 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004938 return AT;
4939}
Jack Carter0b744b32012-10-04 02:29:46 +00004940
Jack Carterd0bd6422013-04-18 00:41:53 +00004941unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004942 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004943}
4944
Toma Tabacu13964452014-09-04 13:23:44 +00004945bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004946 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004947 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004948
Jack Carter30a59822012-10-04 04:03:53 +00004949 // Check if the current operand has a custom associated parser, if so, try to
4950 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004951 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4952 if (ResTy == MatchOperand_Success)
4953 return false;
4954 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4955 // there was a match, but an error occurred, in which case, just return that
4956 // the operand parsing failed.
4957 if (ResTy == MatchOperand_ParseFail)
4958 return true;
4959
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004960 DEBUG(dbgs() << ".. Generic Parser\n");
4961
Jack Carterb4dbc172012-09-05 23:34:03 +00004962 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004963 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004964 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004965 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004966
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004967 // Almost all registers have been parsed by custom parsers. There is only
4968 // one exception to this. $zero (and it's alias $0) will reach this point
4969 // for div, divu, and similar instructions because it is not an operand
4970 // to the instruction definition but an explicit register. Special case
4971 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004972 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004973 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004974
Jack Carterd0bd6422013-04-18 00:41:53 +00004975 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004976 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004977 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004978 return true;
4979
Jack Carter873c7242013-01-12 01:03:14 +00004980 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004981 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004982 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004983 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004984 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004985
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004986 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004987 return false;
4988 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004989 default: {
4990 DEBUG(dbgs() << ".. generic integer expression\n");
4991
4992 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00004993 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004994 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004995 return true;
4996
Jack Carter873c7242013-01-12 01:03:14 +00004997 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4998
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004999 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005000 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005001 }
Jack Carter0b744b32012-10-04 02:29:46 +00005002 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005003 return true;
5004}
5005
Jack Carterb5cf5902013-04-17 00:18:04 +00005006bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005007 switch (Expr->getKind()) {
5008 case MCExpr::Constant:
5009 return true;
5010 case MCExpr::SymbolRef:
5011 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
5012 case MCExpr::Binary:
5013 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
5014 if (!isEvaluated(BE->getLHS()))
5015 return false;
5016 return isEvaluated(BE->getRHS());
5017 }
5018 case MCExpr::Unary:
5019 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005020 case MCExpr::Target:
5021 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005022 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005023 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005024}
Jack Carterd0bd6422013-04-18 00:41:53 +00005025
Jack Carterb4dbc172012-09-05 23:34:03 +00005026bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5027 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005028 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005029 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005030 if (ResTy == MatchOperand_Success) {
5031 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005032 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005033 StartLoc = Operand.getStartLoc();
5034 EndLoc = Operand.getEndLoc();
5035
5036 // AFAIK, we only support numeric registers and named GPR's in CFI
5037 // directives.
5038 // Don't worry about eating tokens before failing. Using an unrecognised
5039 // register is a parse error.
5040 if (Operand.isGPRAsmReg()) {
5041 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005042 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005043 }
5044
5045 return (RegNo == (unsigned)-1);
5046 }
5047
5048 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005049 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005050}
5051
Jack Carterb5cf5902013-04-17 00:18:04 +00005052bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005053 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005054
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005055 if (isParenExpr)
5056 return getParser().parseParenExprOfDepth(0, Res, S);
5057 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005058}
5059
Alex Bradbury58eba092016-11-01 16:32:05 +00005060OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005061MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005062 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005063 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005064 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005065 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005066 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005067 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005068 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005069 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005070
Jack Carterb5cf5902013-04-17 00:18:04 +00005071 if (getLexer().getKind() == AsmToken::LParen) {
5072 Parser.Lex();
5073 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005074 }
5075
Jack Carterb5cf5902013-04-17 00:18:04 +00005076 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005077 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005078 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005079
Jack Carterd0bd6422013-04-18 00:41:53 +00005080 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005081 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005082 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005083 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005084 SMLoc E =
5085 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005086 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005087 return MatchOperand_Success;
5088 }
5089 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005090 SMLoc E =
5091 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005092
Jack Carterd0bd6422013-04-18 00:41:53 +00005093 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005094 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005095 auto Base = MipsOperand::createGPRReg(
5096 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005097 Operands.push_back(
5098 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005099 return MatchOperand_Success;
5100 }
Simon Dardis858915f2016-10-18 15:17:17 +00005101 MCBinaryExpr::Opcode Opcode;
5102 // GAS and LLVM treat comparison operators different. GAS will generate -1
5103 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5104 // highly unlikely to be found in a memory offset expression, we don't
5105 // handle them.
5106 switch (Tok.getKind()) {
5107 case AsmToken::Plus:
5108 Opcode = MCBinaryExpr::Add;
5109 Parser.Lex();
5110 break;
5111 case AsmToken::Minus:
5112 Opcode = MCBinaryExpr::Sub;
5113 Parser.Lex();
5114 break;
5115 case AsmToken::Star:
5116 Opcode = MCBinaryExpr::Mul;
5117 Parser.Lex();
5118 break;
5119 case AsmToken::Pipe:
5120 Opcode = MCBinaryExpr::Or;
5121 Parser.Lex();
5122 break;
5123 case AsmToken::Amp:
5124 Opcode = MCBinaryExpr::And;
5125 Parser.Lex();
5126 break;
5127 case AsmToken::LessLess:
5128 Opcode = MCBinaryExpr::Shl;
5129 Parser.Lex();
5130 break;
5131 case AsmToken::GreaterGreater:
5132 Opcode = MCBinaryExpr::LShr;
5133 Parser.Lex();
5134 break;
5135 case AsmToken::Caret:
5136 Opcode = MCBinaryExpr::Xor;
5137 Parser.Lex();
5138 break;
5139 case AsmToken::Slash:
5140 Opcode = MCBinaryExpr::Div;
5141 Parser.Lex();
5142 break;
5143 case AsmToken::Percent:
5144 Opcode = MCBinaryExpr::Mod;
5145 Parser.Lex();
5146 break;
5147 default:
5148 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5149 return MatchOperand_ParseFail;
5150 }
5151 const MCExpr * NextExpr;
5152 if (getParser().parseExpression(NextExpr))
5153 return MatchOperand_ParseFail;
5154 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005155 }
5156
Jack Carterd0bd6422013-04-18 00:41:53 +00005157 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005158 }
5159
Toma Tabacu13964452014-09-04 13:23:44 +00005160 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005161 if (Res != MatchOperand_Success)
5162 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005163
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005164 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005165 Error(Parser.getTok().getLoc(), "')' expected");
5166 return MatchOperand_ParseFail;
5167 }
5168
Jack Carter873c7242013-01-12 01:03:14 +00005169 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5170
Jack Carterd0bd6422013-04-18 00:41:53 +00005171 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005172
Craig Topper062a2ba2014-04-25 05:30:21 +00005173 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005174 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005175
Jack Carterd0bd6422013-04-18 00:41:53 +00005176 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005177 std::unique_ptr<MipsOperand> op(
5178 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005179 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005180 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005181 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005182 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005183 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5184 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005185 if (IdVal->evaluateAsAbsolute(Imm))
5186 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005187 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005188 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005189 getContext());
5190 }
5191
David Blaikie960ea3f2014-06-08 16:18:35 +00005192 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005193 return MatchOperand_Success;
5194}
5195
David Blaikie960ea3f2014-06-08 16:18:35 +00005196bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005197 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005198 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00005199 if (Sym) {
5200 SMLoc S = Parser.getTok().getLoc();
5201 const MCExpr *Expr;
5202 if (Sym->isVariable())
5203 Expr = Sym->getVariableValue();
5204 else
5205 return false;
5206 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005207 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005208 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005209 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005210 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005211 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005212 if (ResTy == MatchOperand_Success) {
5213 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005214 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00005215 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005216 llvm_unreachable("Should never ParseFail");
5217 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00005218 }
Jack Carterd76b2372013-03-21 21:44:16 +00005219 }
5220 }
5221 return false;
5222}
Jack Carterd0bd6422013-04-18 00:41:53 +00005223
Alex Bradbury58eba092016-11-01 16:32:05 +00005224OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005225MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00005226 StringRef Identifier,
5227 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005228 int Index = matchCPURegisterName(Identifier);
5229 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005230 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005231 Index, Identifier, getContext().getRegisterInfo(), S,
5232 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005233 return MatchOperand_Success;
5234 }
5235
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005236 Index = matchHWRegsRegisterName(Identifier);
5237 if (Index != -1) {
5238 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005239 Index, Identifier, getContext().getRegisterInfo(), S,
5240 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005241 return MatchOperand_Success;
5242 }
5243
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005244 Index = matchFPURegisterName(Identifier);
5245 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005246 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005247 Index, Identifier, getContext().getRegisterInfo(), S,
5248 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005249 return MatchOperand_Success;
5250 }
5251
5252 Index = matchFCCRegisterName(Identifier);
5253 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005254 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005255 Index, Identifier, getContext().getRegisterInfo(), S,
5256 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005257 return MatchOperand_Success;
5258 }
5259
5260 Index = matchACRegisterName(Identifier);
5261 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005262 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005263 Index, Identifier, getContext().getRegisterInfo(), S,
5264 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005265 return MatchOperand_Success;
5266 }
5267
5268 Index = matchMSA128RegisterName(Identifier);
5269 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005270 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005271 Index, Identifier, getContext().getRegisterInfo(), S,
5272 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005273 return MatchOperand_Success;
5274 }
5275
5276 Index = matchMSA128CtrlRegisterName(Identifier);
5277 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005278 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005279 Index, Identifier, getContext().getRegisterInfo(), S,
5280 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005281 return MatchOperand_Success;
5282 }
5283
5284 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00005285}
5286
Alex Bradbury58eba092016-11-01 16:32:05 +00005287OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005288MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005289 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00005290 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005291
5292 if (Token.is(AsmToken::Identifier)) {
5293 DEBUG(dbgs() << ".. identifier\n");
5294 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00005295 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005296 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00005297 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005298 } else if (Token.is(AsmToken::Integer)) {
5299 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00005300 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005301 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
5302 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005303 return MatchOperand_Success;
5304 }
5305
5306 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
5307
5308 return MatchOperand_NoMatch;
5309}
5310
Alex Bradbury58eba092016-11-01 16:32:05 +00005311OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005312MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005313 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005314 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005315
5316 auto Token = Parser.getTok();
5317
5318 SMLoc S = Token.getLoc();
5319
5320 if (Token.isNot(AsmToken::Dollar)) {
5321 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
5322 if (Token.is(AsmToken::Identifier)) {
5323 if (searchSymbolAlias(Operands))
5324 return MatchOperand_Success;
5325 }
5326 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
5327 return MatchOperand_NoMatch;
5328 }
5329 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005330
Toma Tabacu13964452014-09-04 13:23:44 +00005331 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00005332 if (ResTy == MatchOperand_Success) {
5333 Parser.Lex(); // $
5334 Parser.Lex(); // identifier
5335 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005336 return ResTy;
5337}
5338
Alex Bradbury58eba092016-11-01 16:32:05 +00005339OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005340MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005341 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005342 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005343
5344 SMLoc S = getLexer().getLoc();
5345
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005346 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005347 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005348 if (ResTy != MatchOperand_NoMatch)
5349 return ResTy;
5350
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005351 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00005352 const MCExpr *Expr = nullptr;
5353 if (Parser.parseExpression(Expr)) {
5354 // We have no way of knowing if a symbol was consumed so we must ParseFail
5355 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005356 }
Daniel Sandersffd84362014-04-01 10:41:48 +00005357 Operands.push_back(
5358 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005359 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00005360}
5361
Alex Bradbury58eba092016-11-01 16:32:05 +00005362OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005363MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005364 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00005365 const MCExpr *IdVal;
5366 // If the first token is '$' we may have register operand.
5367 if (Parser.getTok().is(AsmToken::Dollar))
5368 return MatchOperand_NoMatch;
5369 SMLoc S = Parser.getTok().getLoc();
5370 if (getParser().parseExpression(IdVal))
5371 return MatchOperand_ParseFail;
5372 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00005373 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00005374 int64_t Val = MCE->getValue();
5375 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5376 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00005377 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00005378 return MatchOperand_Success;
5379}
5380
Alex Bradbury58eba092016-11-01 16:32:05 +00005381OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005382MipsAsmParser::parseRegisterList(OperandVector &Operands) {
5383 MCAsmParser &Parser = getParser();
5384 SmallVector<unsigned, 10> Regs;
5385 unsigned RegNo;
5386 unsigned PrevReg = Mips::NoRegister;
5387 bool RegRange = false;
5388 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5389
5390 if (Parser.getTok().isNot(AsmToken::Dollar))
5391 return MatchOperand_ParseFail;
5392
5393 SMLoc S = Parser.getTok().getLoc();
5394 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
5395 SMLoc E = getLexer().getLoc();
5396 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
5397 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
5398 if (RegRange) {
5399 // Remove last register operand because registers from register range
5400 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005401 if ((isGP64bit() && RegNo == Mips::RA_64) ||
5402 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005403 Regs.push_back(RegNo);
5404 } else {
5405 unsigned TmpReg = PrevReg + 1;
5406 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005407 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
5408 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
5409 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005410 Error(E, "invalid register operand");
5411 return MatchOperand_ParseFail;
5412 }
5413
5414 PrevReg = TmpReg;
5415 Regs.push_back(TmpReg++);
5416 }
5417 }
5418
5419 RegRange = false;
5420 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005421 if ((PrevReg == Mips::NoRegister) &&
5422 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
5423 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005424 Error(E, "$16 or $31 expected");
5425 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005426 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
5427 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
5428 !isGP64bit()) ||
5429 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
5430 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
5431 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005432 Error(E, "invalid register operand");
5433 return MatchOperand_ParseFail;
5434 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005435 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
5436 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
5437 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005438 Error(E, "consecutive register numbers expected");
5439 return MatchOperand_ParseFail;
5440 }
5441
5442 Regs.push_back(RegNo);
5443 }
5444
5445 if (Parser.getTok().is(AsmToken::Minus))
5446 RegRange = true;
5447
5448 if (!Parser.getTok().isNot(AsmToken::Minus) &&
5449 !Parser.getTok().isNot(AsmToken::Comma)) {
5450 Error(E, "',' or '-' expected");
5451 return MatchOperand_ParseFail;
5452 }
5453
5454 Lex(); // Consume comma or minus
5455 if (Parser.getTok().isNot(AsmToken::Dollar))
5456 break;
5457
5458 PrevReg = RegNo;
5459 }
5460
5461 SMLoc E = Parser.getTok().getLoc();
5462 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5463 parseMemOperand(Operands);
5464 return MatchOperand_Success;
5465}
5466
Alex Bradbury58eba092016-11-01 16:32:05 +00005467OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005468MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
5469 MCAsmParser &Parser = getParser();
5470
5471 SMLoc S = Parser.getTok().getLoc();
5472 if (parseAnyRegister(Operands) != MatchOperand_Success)
5473 return MatchOperand_ParseFail;
5474
5475 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00005476 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00005477
Benjamin Kramer2b68d152016-05-09 10:31:17 +00005478 Operands.pop_back();
5479 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005480 return MatchOperand_Success;
5481}
5482
Alex Bradbury58eba092016-11-01 16:32:05 +00005483OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00005484MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
5485 MCAsmParser &Parser = getParser();
5486 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5487 SmallVector<unsigned, 10> Regs;
5488
5489 if (Parser.getTok().isNot(AsmToken::Dollar))
5490 return MatchOperand_ParseFail;
5491
5492 SMLoc S = Parser.getTok().getLoc();
5493
5494 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5495 return MatchOperand_ParseFail;
5496
5497 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5498 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5499 Regs.push_back(RegNo);
5500
5501 SMLoc E = Parser.getTok().getLoc();
5502 if (Parser.getTok().isNot(AsmToken::Comma)) {
5503 Error(E, "',' expected");
5504 return MatchOperand_ParseFail;
5505 }
5506
5507 // Remove comma.
5508 Parser.Lex();
5509
5510 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5511 return MatchOperand_ParseFail;
5512
5513 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5514 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5515 Regs.push_back(RegNo);
5516
5517 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5518
5519 return MatchOperand_Success;
5520}
5521
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005522/// Sometimes (i.e. load/stores) the operand may be followed immediately by
5523/// either this.
5524/// ::= '(', register, ')'
5525/// handle it before we iterate so we don't get tripped up by the lack of
5526/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005527bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005528 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005529 if (getLexer().is(AsmToken::LParen)) {
5530 Operands.push_back(
5531 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
5532 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005533 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005534 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005535 return Error(Loc, "unexpected token in argument list");
5536 }
5537 if (Parser.getTok().isNot(AsmToken::RParen)) {
5538 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005539 return Error(Loc, "unexpected token, expected ')'");
5540 }
5541 Operands.push_back(
5542 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
5543 Parser.Lex();
5544 }
5545 return false;
5546}
5547
5548/// Sometimes (i.e. in MSA) the operand may be followed immediately by
5549/// either one of these.
5550/// ::= '[', register, ']'
5551/// ::= '[', integer, ']'
5552/// handle it before we iterate so we don't get tripped up by the lack of
5553/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005554bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00005555 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005556 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005557 if (getLexer().is(AsmToken::LBrac)) {
5558 Operands.push_back(
5559 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
5560 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005561 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005562 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005563 return Error(Loc, "unexpected token in argument list");
5564 }
5565 if (Parser.getTok().isNot(AsmToken::RBrac)) {
5566 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005567 return Error(Loc, "unexpected token, expected ']'");
5568 }
5569 Operands.push_back(
5570 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
5571 Parser.Lex();
5572 }
5573 return false;
5574}
5575
David Blaikie960ea3f2014-06-08 16:18:35 +00005576bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
5577 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005578 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005579 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005580
5581 // We have reached first instruction, module directive are now forbidden.
5582 getTargetStreamer().forbidModuleDirective();
5583
Vladimir Medic74593e62013-07-17 15:00:42 +00005584 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00005585 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005586 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00005587 }
Vladimir Medic64828a12013-07-16 10:07:14 +00005588 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005589 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005590
5591 // Read the remaining operands.
5592 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5593 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005594 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005595 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005596 return Error(Loc, "unexpected token in argument list");
5597 }
Toma Tabacu13964452014-09-04 13:23:44 +00005598 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005599 return true;
5600 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00005601
Jack Carterd0bd6422013-04-18 00:41:53 +00005602 while (getLexer().is(AsmToken::Comma)) {
5603 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00005604 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005605 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005606 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005607 return Error(Loc, "unexpected token in argument list");
5608 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005609 // Parse bracket and parenthesis suffixes before we iterate
5610 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00005611 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005612 return true;
5613 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00005614 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005615 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005616 }
5617 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005618 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5619 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005620 return Error(Loc, "unexpected token in argument list");
5621 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005622 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00005623 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00005624}
5625
Nirav Dave996fc132016-05-05 14:15:46 +00005626// FIXME: Given that these have the same name, these should both be
5627// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005628bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005629 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005630 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00005631}
5632
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005633bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005634 return Error(Loc, ErrorMsg);
5635}
5636
Jack Carter0b744b32012-10-04 02:29:46 +00005637bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005638 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005639 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00005640
5641 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00005642 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00005643
5644 Parser.Lex(); // Eat "noat".
5645
Jack Carterd0bd6422013-04-18 00:41:53 +00005646 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005647 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005648 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005649 return false;
5650 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005651
5652 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005653 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005654 return false;
5655}
Jack Carterd0bd6422013-04-18 00:41:53 +00005656
Jack Carter0b744b32012-10-04 02:29:46 +00005657bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00005658 // Line can be: ".set at", which sets $at to $1
5659 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00005660 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00005661 Parser.Lex(); // Eat "at".
5662
Jack Carter0b744b32012-10-04 02:29:46 +00005663 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005664 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00005665 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00005666
5667 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005668 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005669 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00005670 }
5671
5672 if (getLexer().isNot(AsmToken::Equal)) {
5673 reportParseError("unexpected token, expected equals sign");
5674 return false;
5675 }
5676 Parser.Lex(); // Eat "=".
5677
5678 if (getLexer().isNot(AsmToken::Dollar)) {
5679 if (getLexer().is(AsmToken::EndOfStatement)) {
5680 reportParseError("no register specified");
5681 return false;
5682 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00005683 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00005684 return false;
5685 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005686 }
5687 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00005688
Toma Tabacu16a74492015-02-13 10:30:57 +00005689 // Find out what "reg" is.
5690 unsigned AtRegNo;
5691 const AsmToken &Reg = Parser.getTok();
5692 if (Reg.is(AsmToken::Identifier)) {
5693 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
5694 } else if (Reg.is(AsmToken::Integer)) {
5695 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00005696 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00005697 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00005698 return false;
5699 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005700
5701 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00005702 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005703 reportParseError("invalid register");
5704 return false;
5705 }
5706 Parser.Lex(); // Eat "reg".
5707
5708 // If this is not the end of the statement, report an error.
5709 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5710 reportParseError("unexpected token, expected end of statement");
5711 return false;
5712 }
5713
5714 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
5715
5716 Parser.Lex(); // Consume the EndOfStatement.
5717 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005718}
5719
5720bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005721 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005722 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005723 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005724 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005725 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005726 return false;
5727 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005728 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00005729 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005730 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005731 return false;
5732}
5733
5734bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005735 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005736 Parser.Lex();
5737 // If this is not the end of the statement, report an error.
5738 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005739 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005740 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005741 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005742 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005743 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005744 Parser.Lex(); // Consume the EndOfStatement.
5745 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005746}
5747
5748bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005749 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005750 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005751 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005752 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005753 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005754 return false;
5755 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005756 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005757 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005758 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005759 return false;
5760}
5761
5762bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005763 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005764 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005765 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005766 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005767 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005768 return false;
5769 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005770 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005771 reportParseError("`noreorder' must be set before `nomacro'");
5772 return false;
5773 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005774 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005775 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005776 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005777 return false;
5778}
Jack Carterd76b2372013-03-21 21:44:16 +00005779
Daniel Sanders44934432014-08-07 12:03:36 +00005780bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005781 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005782 Parser.Lex();
5783
5784 // If this is not the end of the statement, report an error.
5785 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005786 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005787
5788 setFeatureBits(Mips::FeatureMSA, "msa");
5789 getTargetStreamer().emitDirectiveSetMsa();
5790 return false;
5791}
5792
5793bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005794 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005795 Parser.Lex();
5796
5797 // If this is not the end of the statement, report an error.
5798 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005799 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005800
5801 clearFeatureBits(Mips::FeatureMSA, "msa");
5802 getTargetStreamer().emitDirectiveSetNoMsa();
5803 return false;
5804}
5805
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005806bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005807 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005808 Parser.Lex(); // Eat "nodsp".
5809
5810 // If this is not the end of the statement, report an error.
5811 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5812 reportParseError("unexpected token, expected end of statement");
5813 return false;
5814 }
5815
5816 clearFeatureBits(Mips::FeatureDSP, "dsp");
5817 getTargetStreamer().emitDirectiveSetNoDsp();
5818 return false;
5819}
5820
Toma Tabacucc2502d2014-11-04 17:18:07 +00005821bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005822 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005823 Parser.Lex(); // Eat "mips16".
5824
Jack Carter39536722014-01-22 23:08:42 +00005825 // If this is not the end of the statement, report an error.
5826 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005827 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005828 return false;
5829 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005830
5831 setFeatureBits(Mips::FeatureMips16, "mips16");
5832 getTargetStreamer().emitDirectiveSetMips16();
5833 Parser.Lex(); // Consume the EndOfStatement.
5834 return false;
5835}
5836
5837bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005838 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005839 Parser.Lex(); // Eat "nomips16".
5840
5841 // If this is not the end of the statement, report an error.
5842 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5843 reportParseError("unexpected token, expected end of statement");
5844 return false;
5845 }
5846
5847 clearFeatureBits(Mips::FeatureMips16, "mips16");
5848 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005849 Parser.Lex(); // Consume the EndOfStatement.
5850 return false;
5851}
5852
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005853bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005854 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005855 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005856 // Line can be: .set fp=32
5857 // .set fp=xx
5858 // .set fp=64
5859 Parser.Lex(); // Eat fp token
5860 AsmToken Tok = Parser.getTok();
5861 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005862 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005863 return false;
5864 }
5865 Parser.Lex(); // Eat '=' token.
5866 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005867
5868 if (!parseFpABIValue(FpAbiVal, ".set"))
5869 return false;
5870
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005871 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005872 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005873 return false;
5874 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005875 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005876 Parser.Lex(); // Consume the EndOfStatement.
5877 return false;
5878}
5879
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005880bool MipsAsmParser::parseSetOddSPRegDirective() {
5881 MCAsmParser &Parser = getParser();
5882
5883 Parser.Lex(); // Eat "oddspreg".
5884 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5885 reportParseError("unexpected token, expected end of statement");
5886 return false;
5887 }
5888
5889 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5890 getTargetStreamer().emitDirectiveSetOddSPReg();
5891 return false;
5892}
5893
5894bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5895 MCAsmParser &Parser = getParser();
5896
5897 Parser.Lex(); // Eat "nooddspreg".
5898 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5899 reportParseError("unexpected token, expected end of statement");
5900 return false;
5901 }
5902
5903 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5904 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5905 return false;
5906}
5907
Toma Tabacu9db22db2014-09-09 10:15:38 +00005908bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005909 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005910 SMLoc Loc = getLexer().getLoc();
5911
5912 Parser.Lex();
5913 if (getLexer().isNot(AsmToken::EndOfStatement))
5914 return reportParseError("unexpected token, expected end of statement");
5915
5916 // Always keep an element on the options "stack" to prevent the user
5917 // from changing the initial options. This is how we remember them.
5918 if (AssemblerOptions.size() == 2)
5919 return reportParseError(Loc, ".set pop with no .set push");
5920
Akira Hatanakab11ef082015-11-14 06:35:56 +00005921 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005922 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005923 setAvailableFeatures(
5924 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5925 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005926
5927 getTargetStreamer().emitDirectiveSetPop();
5928 return false;
5929}
5930
5931bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005932 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005933 Parser.Lex();
5934 if (getLexer().isNot(AsmToken::EndOfStatement))
5935 return reportParseError("unexpected token, expected end of statement");
5936
5937 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005938 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005939 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005940
5941 getTargetStreamer().emitDirectiveSetPush();
5942 return false;
5943}
5944
Toma Tabacu29696502015-06-02 09:48:04 +00005945bool MipsAsmParser::parseSetSoftFloatDirective() {
5946 MCAsmParser &Parser = getParser();
5947 Parser.Lex();
5948 if (getLexer().isNot(AsmToken::EndOfStatement))
5949 return reportParseError("unexpected token, expected end of statement");
5950
5951 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5952 getTargetStreamer().emitDirectiveSetSoftFloat();
5953 return false;
5954}
5955
5956bool MipsAsmParser::parseSetHardFloatDirective() {
5957 MCAsmParser &Parser = getParser();
5958 Parser.Lex();
5959 if (getLexer().isNot(AsmToken::EndOfStatement))
5960 return reportParseError("unexpected token, expected end of statement");
5961
5962 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5963 getTargetStreamer().emitDirectiveSetHardFloat();
5964 return false;
5965}
5966
Jack Carterd76b2372013-03-21 21:44:16 +00005967bool MipsAsmParser::parseSetAssignment() {
5968 StringRef Name;
5969 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005970 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005971
5972 if (Parser.parseIdentifier(Name))
5973 reportParseError("expected identifier after .set");
5974
5975 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005976 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005977 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005978
Jack Carter3b2c96e2014-01-22 23:31:38 +00005979 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005980 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005981
Jim Grosbach6f482002015-05-18 18:43:14 +00005982 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005983 Sym->setVariableValue(Value);
5984
5985 return false;
5986}
Jack Carterd0bd6422013-04-18 00:41:53 +00005987
Toma Tabacu26647792014-09-09 12:52:14 +00005988bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005989 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005990 Parser.Lex();
5991 if (getLexer().isNot(AsmToken::EndOfStatement))
5992 return reportParseError("unexpected token, expected end of statement");
5993
5994 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005995 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005996 setAvailableFeatures(
5997 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5998 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005999 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6000
6001 getTargetStreamer().emitDirectiveSetMips0();
6002 return false;
6003}
6004
Toma Tabacu85618b32014-08-19 14:22:52 +00006005bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006006 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006007 Parser.Lex();
6008 if (getLexer().isNot(AsmToken::Equal))
6009 return reportParseError("unexpected token, expected equals sign");
6010
6011 Parser.Lex();
6012 StringRef Arch;
6013 if (Parser.parseIdentifier(Arch))
6014 return reportParseError("expected arch identifier");
6015
6016 StringRef ArchFeatureName =
6017 StringSwitch<StringRef>(Arch)
6018 .Case("mips1", "mips1")
6019 .Case("mips2", "mips2")
6020 .Case("mips3", "mips3")
6021 .Case("mips4", "mips4")
6022 .Case("mips5", "mips5")
6023 .Case("mips32", "mips32")
6024 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006025 .Case("mips32r3", "mips32r3")
6026 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006027 .Case("mips32r6", "mips32r6")
6028 .Case("mips64", "mips64")
6029 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006030 .Case("mips64r3", "mips64r3")
6031 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006032 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006033 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006034 .Case("r4000", "mips3") // This is an implementation of Mips3.
6035 .Default("");
6036
6037 if (ArchFeatureName.empty())
6038 return reportParseError("unsupported architecture");
6039
6040 selectArch(ArchFeatureName);
6041 getTargetStreamer().emitDirectiveSetArch(Arch);
6042 return false;
6043}
6044
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006045bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006046 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006047 Parser.Lex();
6048 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006049 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006050
Matheus Almeida2852af82014-04-22 10:15:54 +00006051 switch (Feature) {
6052 default:
6053 llvm_unreachable("Unimplemented feature");
6054 case Mips::FeatureDSP:
6055 setFeatureBits(Mips::FeatureDSP, "dsp");
6056 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006057 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006058 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006059 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006060 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006061 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006062 case Mips::FeatureMips1:
6063 selectArch("mips1");
6064 getTargetStreamer().emitDirectiveSetMips1();
6065 break;
6066 case Mips::FeatureMips2:
6067 selectArch("mips2");
6068 getTargetStreamer().emitDirectiveSetMips2();
6069 break;
6070 case Mips::FeatureMips3:
6071 selectArch("mips3");
6072 getTargetStreamer().emitDirectiveSetMips3();
6073 break;
6074 case Mips::FeatureMips4:
6075 selectArch("mips4");
6076 getTargetStreamer().emitDirectiveSetMips4();
6077 break;
6078 case Mips::FeatureMips5:
6079 selectArch("mips5");
6080 getTargetStreamer().emitDirectiveSetMips5();
6081 break;
6082 case Mips::FeatureMips32:
6083 selectArch("mips32");
6084 getTargetStreamer().emitDirectiveSetMips32();
6085 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006086 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006087 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006088 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006089 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006090 case Mips::FeatureMips32r3:
6091 selectArch("mips32r3");
6092 getTargetStreamer().emitDirectiveSetMips32R3();
6093 break;
6094 case Mips::FeatureMips32r5:
6095 selectArch("mips32r5");
6096 getTargetStreamer().emitDirectiveSetMips32R5();
6097 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006098 case Mips::FeatureMips32r6:
6099 selectArch("mips32r6");
6100 getTargetStreamer().emitDirectiveSetMips32R6();
6101 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006102 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006103 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006104 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006105 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006106 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006107 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006108 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006109 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006110 case Mips::FeatureMips64r3:
6111 selectArch("mips64r3");
6112 getTargetStreamer().emitDirectiveSetMips64R3();
6113 break;
6114 case Mips::FeatureMips64r5:
6115 selectArch("mips64r5");
6116 getTargetStreamer().emitDirectiveSetMips64R5();
6117 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006118 case Mips::FeatureMips64r6:
6119 selectArch("mips64r6");
6120 getTargetStreamer().emitDirectiveSetMips64R6();
6121 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006122 }
6123 return false;
6124}
6125
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006126bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006127 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006128 if (getLexer().isNot(AsmToken::Comma)) {
6129 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006130 return Error(Loc, ErrorStr);
6131 }
6132
Matheus Almeida2852af82014-04-22 10:15:54 +00006133 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006134 return true;
6135}
6136
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006137// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
6138// In this class, it is only used for .cprestore.
6139// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
6140// MipsTargetELFStreamer and MipsAsmParser.
6141bool MipsAsmParser::isPicAndNotNxxAbi() {
6142 return inPicMode() && !(isABI_N32() || isABI_N64());
6143}
6144
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006145bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00006146 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00006147 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006148
Toma Tabacudde4c462014-11-06 10:02:45 +00006149 if (inMips16Mode()) {
6150 reportParseError(".cpload is not supported in Mips16 mode");
6151 return false;
6152 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006153
David Blaikie960ea3f2014-06-08 16:18:35 +00006154 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00006155 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006156 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6157 reportParseError("expected register containing function address");
6158 return false;
6159 }
6160
David Blaikie960ea3f2014-06-08 16:18:35 +00006161 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
6162 if (!RegOpnd.isGPRAsmReg()) {
6163 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006164 return false;
6165 }
6166
Toma Tabacudde4c462014-11-06 10:02:45 +00006167 // If this is not the end of the statement, report an error.
6168 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6169 reportParseError("unexpected token, expected end of statement");
6170 return false;
6171 }
6172
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006173 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006174 return false;
6175}
6176
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006177bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
6178 MCAsmParser &Parser = getParser();
6179
6180 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
6181 // is used in non-PIC mode.
6182
6183 if (inMips16Mode()) {
6184 reportParseError(".cprestore is not supported in Mips16 mode");
6185 return false;
6186 }
6187
6188 // Get the stack offset value.
6189 const MCExpr *StackOffset;
6190 int64_t StackOffsetVal;
6191 if (Parser.parseExpression(StackOffset)) {
6192 reportParseError("expected stack offset value");
6193 return false;
6194 }
6195
6196 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
6197 reportParseError("stack offset is not an absolute expression");
6198 return false;
6199 }
6200
6201 if (StackOffsetVal < 0) {
6202 Warning(Loc, ".cprestore with negative stack offset has no effect");
6203 IsCpRestoreSet = false;
6204 } else {
6205 IsCpRestoreSet = true;
6206 CpRestoreOffset = StackOffsetVal;
6207 }
6208
6209 // If this is not the end of the statement, report an error.
6210 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6211 reportParseError("unexpected token, expected end of statement");
6212 return false;
6213 }
6214
Daniel Sandersdf8510d2016-05-11 12:48:19 +00006215 if (!getTargetStreamer().emitDirectiveCpRestore(
6216 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00006217 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006218 Parser.Lex(); // Consume the EndOfStatement.
6219 return false;
6220}
6221
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006222bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006223 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006224 unsigned FuncReg;
6225 unsigned Save;
6226 bool SaveIsReg = true;
6227
Matheus Almeida7e815762014-06-18 13:08:59 +00006228 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006229 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006230 if (ResTy == MatchOperand_NoMatch) {
6231 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00006232 return false;
6233 }
6234
6235 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6236 if (!FuncRegOpnd.isGPRAsmReg()) {
6237 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006238 return false;
6239 }
6240
6241 FuncReg = FuncRegOpnd.getGPR32Reg();
6242 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006243
Toma Tabacu65f10572014-09-16 15:00:52 +00006244 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006245 return true;
6246
Toma Tabacu13964452014-09-04 13:23:44 +00006247 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006248 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00006249 const MCExpr *OffsetExpr;
6250 int64_t OffsetVal;
6251 SMLoc ExprLoc = getLexer().getLoc();
6252
6253 if (Parser.parseExpression(OffsetExpr) ||
6254 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
6255 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00006256 return false;
6257 }
Daniel Sanders5d796282015-09-21 09:26:55 +00006258
6259 Save = OffsetVal;
6260 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00006261 } else {
6262 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6263 if (!SaveOpnd.isGPRAsmReg()) {
6264 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006265 return false;
6266 }
6267 Save = SaveOpnd.getGPR32Reg();
6268 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006269
Toma Tabacu65f10572014-09-16 15:00:52 +00006270 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006271 return true;
6272
Toma Tabacu8874eac2015-02-18 13:46:53 +00006273 const MCExpr *Expr;
6274 if (Parser.parseExpression(Expr)) {
6275 reportParseError("expected expression");
6276 return false;
6277 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006278
Toma Tabacu8874eac2015-02-18 13:46:53 +00006279 if (Expr->getKind() != MCExpr::SymbolRef) {
6280 reportParseError("expected symbol");
6281 return false;
6282 }
6283 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
6284
Daniel Sandersf173dda2015-09-22 10:50:09 +00006285 CpSaveLocation = Save;
6286 CpSaveLocationIsRegister = SaveIsReg;
6287
Toma Tabacu8874eac2015-02-18 13:46:53 +00006288 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
6289 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006290 return false;
6291}
6292
Daniel Sandersf173dda2015-09-22 10:50:09 +00006293bool MipsAsmParser::parseDirectiveCPReturn() {
6294 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
6295 CpSaveLocationIsRegister);
6296 return false;
6297}
6298
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006299bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006300 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006301 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6302 const AsmToken &Tok = Parser.getTok();
6303
6304 if (Tok.getString() == "2008") {
6305 Parser.Lex();
6306 getTargetStreamer().emitDirectiveNaN2008();
6307 return false;
6308 } else if (Tok.getString() == "legacy") {
6309 Parser.Lex();
6310 getTargetStreamer().emitDirectiveNaNLegacy();
6311 return false;
6312 }
6313 }
6314 // If we don't recognize the option passed to the .nan
6315 // directive (e.g. no option or unknown option), emit an error.
6316 reportParseError("invalid option in .nan directive");
6317 return false;
6318}
6319
Jack Carter0b744b32012-10-04 02:29:46 +00006320bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006321 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006322 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00006323 const AsmToken &Tok = Parser.getTok();
6324
6325 if (Tok.getString() == "noat") {
6326 return parseSetNoAtDirective();
6327 } else if (Tok.getString() == "at") {
6328 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00006329 } else if (Tok.getString() == "arch") {
6330 return parseSetArchDirective();
Simon Dardisac9c30c2017-02-01 18:50:24 +00006331 } else if (Tok.getString() == "bopt") {
6332 Warning(Tok.getLoc(), "'bopt' feature is unsupported");
6333 getParser().Lex();
6334 return false;
6335 } else if (Tok.getString() == "nobopt") {
6336 // We're already running in nobopt mode, so nothing to do.
6337 getParser().Lex();
6338 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006339 } else if (Tok.getString() == "fp") {
6340 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006341 } else if (Tok.getString() == "oddspreg") {
6342 return parseSetOddSPRegDirective();
6343 } else if (Tok.getString() == "nooddspreg") {
6344 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006345 } else if (Tok.getString() == "pop") {
6346 return parseSetPopDirective();
6347 } else if (Tok.getString() == "push") {
6348 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00006349 } else if (Tok.getString() == "reorder") {
6350 return parseSetReorderDirective();
6351 } else if (Tok.getString() == "noreorder") {
6352 return parseSetNoReorderDirective();
6353 } else if (Tok.getString() == "macro") {
6354 return parseSetMacroDirective();
6355 } else if (Tok.getString() == "nomacro") {
6356 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00006357 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00006358 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006359 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00006360 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006361 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00006362 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00006363 getTargetStreamer().emitDirectiveSetNoMicroMips();
6364 Parser.eatToEndOfStatement();
6365 return false;
6366 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006367 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00006368 } else if (Tok.getString() == "mips0") {
6369 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00006370 } else if (Tok.getString() == "mips1") {
6371 return parseSetFeature(Mips::FeatureMips1);
6372 } else if (Tok.getString() == "mips2") {
6373 return parseSetFeature(Mips::FeatureMips2);
6374 } else if (Tok.getString() == "mips3") {
6375 return parseSetFeature(Mips::FeatureMips3);
6376 } else if (Tok.getString() == "mips4") {
6377 return parseSetFeature(Mips::FeatureMips4);
6378 } else if (Tok.getString() == "mips5") {
6379 return parseSetFeature(Mips::FeatureMips5);
6380 } else if (Tok.getString() == "mips32") {
6381 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00006382 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006383 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006384 } else if (Tok.getString() == "mips32r3") {
6385 return parseSetFeature(Mips::FeatureMips32r3);
6386 } else if (Tok.getString() == "mips32r5") {
6387 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006388 } else if (Tok.getString() == "mips32r6") {
6389 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006390 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006391 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006392 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006393 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006394 } else if (Tok.getString() == "mips64r3") {
6395 return parseSetFeature(Mips::FeatureMips64r3);
6396 } else if (Tok.getString() == "mips64r5") {
6397 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006398 } else if (Tok.getString() == "mips64r6") {
6399 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00006400 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006401 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006402 } else if (Tok.getString() == "nodsp") {
6403 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00006404 } else if (Tok.getString() == "msa") {
6405 return parseSetMsaDirective();
6406 } else if (Tok.getString() == "nomsa") {
6407 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00006408 } else if (Tok.getString() == "softfloat") {
6409 return parseSetSoftFloatDirective();
6410 } else if (Tok.getString() == "hardfloat") {
6411 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00006412 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00006413 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00006414 parseSetAssignment();
6415 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006416 }
Jack Carter07c818d2013-01-25 01:31:34 +00006417
Jack Carter0b744b32012-10-04 02:29:46 +00006418 return true;
6419}
6420
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006421/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00006422/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006423bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006424 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006425 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006426 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00006427 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00006428 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00006429 return true;
6430
6431 getParser().getStreamer().EmitValue(Value, Size);
6432
6433 if (getLexer().is(AsmToken::EndOfStatement))
6434 break;
6435
Jack Carter07c818d2013-01-25 01:31:34 +00006436 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006437 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00006438 Parser.Lex();
6439 }
6440 }
6441
6442 Parser.Lex();
6443 return false;
6444}
6445
Vladimir Medic4c299852013-11-06 11:27:05 +00006446/// parseDirectiveGpWord
6447/// ::= .gpword local_sym
6448bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006449 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00006450 const MCExpr *Value;
6451 // EmitGPRel32Value requires an expression, so we are using base class
6452 // method to evaluate the expression.
6453 if (getParser().parseExpression(Value))
6454 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00006455 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00006456
Vladimir Medice10c1122013-11-13 13:18:04 +00006457 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006458 return Error(getLexer().getLoc(),
6459 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00006460 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00006461 return false;
6462}
6463
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006464/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00006465/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006466bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006467 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006468 const MCExpr *Value;
6469 // EmitGPRel64Value requires an expression, so we are using base class
6470 // method to evaluate the expression.
6471 if (getParser().parseExpression(Value))
6472 return true;
6473 getParser().getStreamer().EmitGPRel64Value(Value);
6474
6475 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006476 return Error(getLexer().getLoc(),
6477 "unexpected token, expected end of statement");
6478 Parser.Lex(); // Eat EndOfStatement token.
6479 return false;
6480}
6481
6482/// parseDirectiveDtpRelWord
6483/// ::= .dtprelword tls_sym
6484bool MipsAsmParser::parseDirectiveDtpRelWord() {
6485 MCAsmParser &Parser = getParser();
6486 const MCExpr *Value;
6487 // EmitDTPRel32Value requires an expression, so we are using base class
6488 // method to evaluate the expression.
6489 if (getParser().parseExpression(Value))
6490 return true;
6491 getParser().getStreamer().EmitDTPRel32Value(Value);
6492
6493 if (getLexer().isNot(AsmToken::EndOfStatement))
6494 return Error(getLexer().getLoc(),
6495 "unexpected token, expected end of statement");
6496 Parser.Lex(); // Eat EndOfStatement token.
6497 return false;
6498}
6499
6500/// parseDirectiveDtpRelDWord
6501/// ::= .dtpreldword tls_sym
6502bool MipsAsmParser::parseDirectiveDtpRelDWord() {
6503 MCAsmParser &Parser = getParser();
6504 const MCExpr *Value;
6505 // EmitDTPRel64Value requires an expression, so we are using base class
6506 // method to evaluate the expression.
6507 if (getParser().parseExpression(Value))
6508 return true;
6509 getParser().getStreamer().EmitDTPRel64Value(Value);
6510
6511 if (getLexer().isNot(AsmToken::EndOfStatement))
6512 return Error(getLexer().getLoc(),
6513 "unexpected token, expected end of statement");
6514 Parser.Lex(); // Eat EndOfStatement token.
6515 return false;
6516}
6517
6518/// parseDirectiveTpRelWord
6519/// ::= .tprelword tls_sym
6520bool MipsAsmParser::parseDirectiveTpRelWord() {
6521 MCAsmParser &Parser = getParser();
6522 const MCExpr *Value;
6523 // EmitTPRel32Value requires an expression, so we are using base class
6524 // method to evaluate the expression.
6525 if (getParser().parseExpression(Value))
6526 return true;
6527 getParser().getStreamer().EmitTPRel32Value(Value);
6528
6529 if (getLexer().isNot(AsmToken::EndOfStatement))
6530 return Error(getLexer().getLoc(),
6531 "unexpected token, expected end of statement");
6532 Parser.Lex(); // Eat EndOfStatement token.
6533 return false;
6534}
6535
6536/// parseDirectiveTpRelDWord
6537/// ::= .tpreldword tls_sym
6538bool MipsAsmParser::parseDirectiveTpRelDWord() {
6539 MCAsmParser &Parser = getParser();
6540 const MCExpr *Value;
6541 // EmitTPRel64Value requires an expression, so we are using base class
6542 // method to evaluate the expression.
6543 if (getParser().parseExpression(Value))
6544 return true;
6545 getParser().getStreamer().EmitTPRel64Value(Value);
6546
6547 if (getLexer().isNot(AsmToken::EndOfStatement))
6548 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00006549 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00006550 Parser.Lex(); // Eat EndOfStatement token.
6551 return false;
6552}
6553
Jack Carter0cd3c192014-01-06 23:27:31 +00006554bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006555 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00006556 // Get the option token.
6557 AsmToken Tok = Parser.getTok();
6558 // At the moment only identifiers are supported.
6559 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006560 return Error(Parser.getTok().getLoc(),
6561 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00006562 }
6563
6564 StringRef Option = Tok.getIdentifier();
6565
6566 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006567 // MipsAsmParser needs to know if the current PIC mode changes.
6568 IsPicEnabled = false;
6569
Jack Carter0cd3c192014-01-06 23:27:31 +00006570 getTargetStreamer().emitDirectiveOptionPic0();
6571 Parser.Lex();
6572 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006573 return Error(Parser.getTok().getLoc(),
6574 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006575 }
6576 return false;
6577 }
6578
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006579 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006580 // MipsAsmParser needs to know if the current PIC mode changes.
6581 IsPicEnabled = true;
6582
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006583 getTargetStreamer().emitDirectiveOptionPic2();
6584 Parser.Lex();
6585 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006586 return Error(Parser.getTok().getLoc(),
6587 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006588 }
6589 return false;
6590 }
6591
Jack Carter0cd3c192014-01-06 23:27:31 +00006592 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00006593 Warning(Parser.getTok().getLoc(),
6594 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00006595 Parser.eatToEndOfStatement();
6596 return false;
6597}
6598
Toma Tabacu9ca50962015-04-16 09:53:47 +00006599/// parseInsnDirective
6600/// ::= .insn
6601bool MipsAsmParser::parseInsnDirective() {
6602 // If this is not the end of the statement, report an error.
6603 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6604 reportParseError("unexpected token, expected end of statement");
6605 return false;
6606 }
6607
6608 // The actual label marking happens in
6609 // MipsELFStreamer::createPendingLabelRelocs().
6610 getTargetStreamer().emitDirectiveInsn();
6611
6612 getParser().Lex(); // Eat EndOfStatement token.
6613 return false;
6614}
6615
Simon Atanasyanbe186202016-02-11 06:45:54 +00006616/// parseSSectionDirective
6617/// ::= .sbss
6618/// ::= .sdata
6619bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
6620 // If this is not the end of the statement, report an error.
6621 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6622 reportParseError("unexpected token, expected end of statement");
6623 return false;
6624 }
6625
6626 MCSection *ELFSection = getContext().getELFSection(
6627 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
6628 getParser().getStreamer().SwitchSection(ELFSection);
6629
6630 getParser().Lex(); // Eat EndOfStatement token.
6631 return false;
6632}
6633
Daniel Sanders7e527422014-07-10 13:38:23 +00006634/// parseDirectiveModule
6635/// ::= .module oddspreg
6636/// ::= .module nooddspreg
6637/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00006638/// ::= .module softfloat
6639/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006640bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006641 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006642 MCAsmLexer &Lexer = getLexer();
6643 SMLoc L = Lexer.getLoc();
6644
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006645 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006646 // TODO : get a better message.
6647 reportParseError(".module directive must appear before any code");
6648 return false;
6649 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006650
Toma Tabacuc405c822015-01-23 10:40:19 +00006651 StringRef Option;
6652 if (Parser.parseIdentifier(Option)) {
6653 reportParseError("expected .module option identifier");
6654 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006655 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006656
Toma Tabacuc405c822015-01-23 10:40:19 +00006657 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006658 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006659
Toma Tabacu3c499582015-06-25 10:56:57 +00006660 // Synchronize the abiflags information with the FeatureBits information we
6661 // changed above.
6662 getTargetStreamer().updateABIInfo(*this);
6663
6664 // If printing assembly, use the recently updated abiflags information.
6665 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6666 // emitted at the end).
6667 getTargetStreamer().emitDirectiveModuleOddSPReg();
6668
Toma Tabacuc405c822015-01-23 10:40:19 +00006669 // If this is not the end of the statement, report an error.
6670 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6671 reportParseError("unexpected token, expected end of statement");
6672 return false;
6673 }
6674
6675 return false; // parseDirectiveModule has finished successfully.
6676 } else if (Option == "nooddspreg") {
6677 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006678 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00006679 }
6680
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006681 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006682
Toma Tabacu3c499582015-06-25 10:56:57 +00006683 // Synchronize the abiflags information with the FeatureBits information we
6684 // changed above.
6685 getTargetStreamer().updateABIInfo(*this);
6686
6687 // If printing assembly, use the recently updated abiflags information.
6688 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6689 // emitted at the end).
6690 getTargetStreamer().emitDirectiveModuleOddSPReg();
6691
Toma Tabacuc405c822015-01-23 10:40:19 +00006692 // If this is not the end of the statement, report an error.
6693 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6694 reportParseError("unexpected token, expected end of statement");
6695 return false;
6696 }
6697
6698 return false; // parseDirectiveModule has finished successfully.
6699 } else if (Option == "fp") {
6700 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00006701 } else if (Option == "softfloat") {
6702 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6703
6704 // Synchronize the ABI Flags information with the FeatureBits information we
6705 // updated above.
6706 getTargetStreamer().updateABIInfo(*this);
6707
6708 // If printing assembly, use the recently updated ABI Flags information.
6709 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6710 // emitted later).
6711 getTargetStreamer().emitDirectiveModuleSoftFloat();
6712
6713 // If this is not the end of the statement, report an error.
6714 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6715 reportParseError("unexpected token, expected end of statement");
6716 return false;
6717 }
6718
6719 return false; // parseDirectiveModule has finished successfully.
6720 } else if (Option == "hardfloat") {
6721 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6722
6723 // Synchronize the ABI Flags information with the FeatureBits information we
6724 // updated above.
6725 getTargetStreamer().updateABIInfo(*this);
6726
6727 // If printing assembly, use the recently updated ABI Flags information.
6728 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6729 // emitted later).
6730 getTargetStreamer().emitDirectiveModuleHardFloat();
6731
6732 // If this is not the end of the statement, report an error.
6733 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6734 reportParseError("unexpected token, expected end of statement");
6735 return false;
6736 }
6737
6738 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00006739 } else {
6740 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
6741 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006742}
6743
6744/// parseDirectiveModuleFP
6745/// ::= =32
6746/// ::= =xx
6747/// ::= =64
6748bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006749 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006750 MCAsmLexer &Lexer = getLexer();
6751
6752 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006753 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006754 return false;
6755 }
6756 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006757
Daniel Sanders7e527422014-07-10 13:38:23 +00006758 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006759 if (!parseFpABIValue(FpABI, ".module"))
6760 return false;
6761
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006762 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006763 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006764 return false;
6765 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006766
Toma Tabacua64e5402015-06-25 12:44:38 +00006767 // Synchronize the abiflags information with the FeatureBits information we
6768 // changed above.
6769 getTargetStreamer().updateABIInfo(*this);
6770
6771 // If printing assembly, use the recently updated abiflags information.
6772 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6773 // emitted at the end).
6774 getTargetStreamer().emitDirectiveModuleFP();
6775
Daniel Sanders7e527422014-07-10 13:38:23 +00006776 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006777 return false;
6778}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006779
Daniel Sanders7e527422014-07-10 13:38:23 +00006780bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006781 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006782 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006783 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006784 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006785
6786 if (Lexer.is(AsmToken::Identifier)) {
6787 StringRef Value = Parser.getTok().getString();
6788 Parser.Lex();
6789
6790 if (Value != "xx") {
6791 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6792 return false;
6793 }
6794
6795 if (!isABI_O32()) {
6796 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
6797 return false;
6798 }
6799
Daniel Sanders7e527422014-07-10 13:38:23 +00006800 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006801 if (ModuleLevelOptions) {
6802 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6803 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6804 } else {
6805 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6806 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6807 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006808 return true;
6809 }
6810
6811 if (Lexer.is(AsmToken::Integer)) {
6812 unsigned Value = Parser.getTok().getIntVal();
6813 Parser.Lex();
6814
6815 if (Value != 32 && Value != 64) {
6816 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6817 return false;
6818 }
6819
6820 if (Value == 32) {
6821 if (!isABI_O32()) {
6822 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6823 return false;
6824 }
6825
Daniel Sanders7e527422014-07-10 13:38:23 +00006826 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006827 if (ModuleLevelOptions) {
6828 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6829 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6830 } else {
6831 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6832 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6833 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006834 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006835 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006836 if (ModuleLevelOptions) {
6837 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6838 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6839 } else {
6840 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6841 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6842 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006843 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006844
Daniel Sanders7e527422014-07-10 13:38:23 +00006845 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006846 }
6847
6848 return false;
6849}
6850
Jack Carter0b744b32012-10-04 02:29:46 +00006851bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006852 // This returns false if this function recognizes the directive
6853 // regardless of whether it is successfully handles or reports an
6854 // error. Otherwise it returns true to give the generic parser a
6855 // chance at recognizing it.
6856
Rafael Espindola961d4692014-11-11 05:18:41 +00006857 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006858 StringRef IDVal = DirectiveID.getString();
6859
Nirav Dave996fc132016-05-05 14:15:46 +00006860 if (IDVal == ".cpload") {
6861 parseDirectiveCpLoad(DirectiveID.getLoc());
6862 return false;
6863 }
6864 if (IDVal == ".cprestore") {
6865 parseDirectiveCpRestore(DirectiveID.getLoc());
6866 return false;
6867 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006868 if (IDVal == ".dword") {
6869 parseDataDirective(8, DirectiveID.getLoc());
6870 return false;
6871 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006872 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006873 StringRef SymbolName;
6874
6875 if (Parser.parseIdentifier(SymbolName)) {
6876 reportParseError("expected identifier after .ent");
6877 return false;
6878 }
6879
6880 // There's an undocumented extension that allows an integer to
6881 // follow the name of the procedure which AFAICS is ignored by GAS.
6882 // Example: .ent foo,2
6883 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6884 if (getLexer().isNot(AsmToken::Comma)) {
6885 // Even though we accept this undocumented extension for compatibility
6886 // reasons, the additional integer argument does not actually change
6887 // the behaviour of the '.ent' directive, so we would like to discourage
6888 // its use. We do this by not referring to the extended version in
6889 // error messages which are not directly related to its use.
6890 reportParseError("unexpected token, expected end of statement");
6891 return false;
6892 }
6893 Parser.Lex(); // Eat the comma.
6894 const MCExpr *DummyNumber;
6895 int64_t DummyNumberVal;
6896 // If the user was explicitly trying to use the extended version,
6897 // we still give helpful extension-related error messages.
6898 if (Parser.parseExpression(DummyNumber)) {
6899 reportParseError("expected number after comma");
6900 return false;
6901 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006902 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006903 reportParseError("expected an absolute expression after comma");
6904 return false;
6905 }
6906 }
6907
6908 // If this is not the end of the statement, report an error.
6909 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6910 reportParseError("unexpected token, expected end of statement");
6911 return false;
6912 }
6913
Jim Grosbach6f482002015-05-18 18:43:14 +00006914 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006915
6916 getTargetStreamer().emitDirectiveEnt(*Sym);
6917 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006918 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006919 return false;
6920 }
6921
Jack Carter07c818d2013-01-25 01:31:34 +00006922 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006923 StringRef SymbolName;
6924
6925 if (Parser.parseIdentifier(SymbolName)) {
6926 reportParseError("expected identifier after .end");
6927 return false;
6928 }
6929
6930 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6931 reportParseError("unexpected token, expected end of statement");
6932 return false;
6933 }
6934
6935 if (CurrentFn == nullptr) {
6936 reportParseError(".end used without .ent");
6937 return false;
6938 }
6939
6940 if ((SymbolName != CurrentFn->getName())) {
6941 reportParseError(".end symbol does not match .ent symbol");
6942 return false;
6943 }
6944
6945 getTargetStreamer().emitDirectiveEnd(SymbolName);
6946 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006947 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006948 return false;
6949 }
6950
Jack Carter07c818d2013-01-25 01:31:34 +00006951 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006952 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6953 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006954 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006955 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6956 reportParseError("expected stack register");
6957 return false;
6958 }
6959
6960 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6961 if (!StackRegOpnd.isGPRAsmReg()) {
6962 reportParseError(StackRegOpnd.getStartLoc(),
6963 "expected general purpose register");
6964 return false;
6965 }
6966 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6967
6968 if (Parser.getTok().is(AsmToken::Comma))
6969 Parser.Lex();
6970 else {
6971 reportParseError("unexpected token, expected comma");
6972 return false;
6973 }
6974
6975 // Parse the frame size.
6976 const MCExpr *FrameSize;
6977 int64_t FrameSizeVal;
6978
6979 if (Parser.parseExpression(FrameSize)) {
6980 reportParseError("expected frame size value");
6981 return false;
6982 }
6983
Jim Grosbach13760bd2015-05-30 01:25:56 +00006984 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006985 reportParseError("frame size not an absolute expression");
6986 return false;
6987 }
6988
6989 if (Parser.getTok().is(AsmToken::Comma))
6990 Parser.Lex();
6991 else {
6992 reportParseError("unexpected token, expected comma");
6993 return false;
6994 }
6995
6996 // Parse the return register.
6997 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006998 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006999 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7000 reportParseError("expected return register");
7001 return false;
7002 }
7003
7004 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7005 if (!ReturnRegOpnd.isGPRAsmReg()) {
7006 reportParseError(ReturnRegOpnd.getStartLoc(),
7007 "expected general purpose register");
7008 return false;
7009 }
7010
7011 // If this is not the end of the statement, report an error.
7012 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7013 reportParseError("unexpected token, expected end of statement");
7014 return false;
7015 }
7016
7017 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
7018 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007019 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007020 return false;
7021 }
7022
Jack Carter07c818d2013-01-25 01:31:34 +00007023 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00007024 parseDirectiveSet();
7025 return false;
Jack Carterbe332172012-09-07 00:48:02 +00007026 }
7027
Daniel Sandersd97a6342014-08-13 10:07:34 +00007028 if (IDVal == ".mask" || IDVal == ".fmask") {
7029 // .mask bitmask, frame_offset
7030 // bitmask: One bit for each register used.
7031 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
7032 // first register is expected to be saved.
7033 // Examples:
7034 // .mask 0x80000000, -4
7035 // .fmask 0x80000000, -4
7036 //
Jack Carterbe332172012-09-07 00:48:02 +00007037
Daniel Sandersd97a6342014-08-13 10:07:34 +00007038 // Parse the bitmask
7039 const MCExpr *BitMask;
7040 int64_t BitMaskVal;
7041
7042 if (Parser.parseExpression(BitMask)) {
7043 reportParseError("expected bitmask value");
7044 return false;
7045 }
7046
Jim Grosbach13760bd2015-05-30 01:25:56 +00007047 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007048 reportParseError("bitmask not an absolute expression");
7049 return false;
7050 }
7051
7052 if (Parser.getTok().is(AsmToken::Comma))
7053 Parser.Lex();
7054 else {
7055 reportParseError("unexpected token, expected comma");
7056 return false;
7057 }
7058
7059 // Parse the frame_offset
7060 const MCExpr *FrameOffset;
7061 int64_t FrameOffsetVal;
7062
7063 if (Parser.parseExpression(FrameOffset)) {
7064 reportParseError("expected frame offset value");
7065 return false;
7066 }
7067
Jim Grosbach13760bd2015-05-30 01:25:56 +00007068 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007069 reportParseError("frame offset not an absolute expression");
7070 return false;
7071 }
7072
7073 // If this is not the end of the statement, report an error.
7074 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7075 reportParseError("unexpected token, expected end of statement");
7076 return false;
7077 }
7078
7079 if (IDVal == ".mask")
7080 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
7081 else
7082 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00007083 return false;
7084 }
7085
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007086 if (IDVal == ".nan")
7087 return parseDirectiveNaN();
7088
Jack Carter07c818d2013-01-25 01:31:34 +00007089 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00007090 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00007091 return false;
7092 }
7093
Rafael Espindolab59fb732014-03-28 18:50:26 +00007094 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007095 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007096 return false;
7097 }
7098
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007099 if (IDVal == ".dtprelword") {
7100 parseDirectiveDtpRelWord();
7101 return false;
7102 }
7103
7104 if (IDVal == ".dtpreldword") {
7105 parseDirectiveDtpRelDWord();
7106 return false;
7107 }
7108
7109 if (IDVal == ".tprelword") {
7110 parseDirectiveTpRelWord();
7111 return false;
7112 }
7113
7114 if (IDVal == ".tpreldword") {
7115 parseDirectiveTpRelDWord();
7116 return false;
7117 }
7118
Jack Carter07c818d2013-01-25 01:31:34 +00007119 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007120 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00007121 return false;
7122 }
7123
Scott Egertond1aeb052016-02-15 16:11:51 +00007124 if (IDVal == ".hword") {
7125 parseDataDirective(2, DirectiveID.getLoc());
7126 return false;
7127 }
7128
Nirav Dave996fc132016-05-05 14:15:46 +00007129 if (IDVal == ".option") {
7130 parseDirectiveOption();
7131 return false;
7132 }
Jack Carter0cd3c192014-01-06 23:27:31 +00007133
7134 if (IDVal == ".abicalls") {
7135 getTargetStreamer().emitDirectiveAbiCalls();
7136 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007137 Error(Parser.getTok().getLoc(),
7138 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007139 }
7140 return false;
7141 }
7142
Nirav Dave996fc132016-05-05 14:15:46 +00007143 if (IDVal == ".cpsetup") {
7144 parseDirectiveCPSetup();
7145 return false;
7146 }
7147 if (IDVal == ".cpreturn") {
7148 parseDirectiveCPReturn();
7149 return false;
7150 }
7151 if (IDVal == ".module") {
7152 parseDirectiveModule();
7153 return false;
7154 }
7155 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
7156 parseInternalDirectiveReallowModule();
7157 return false;
7158 }
7159 if (IDVal == ".insn") {
7160 parseInsnDirective();
7161 return false;
7162 }
7163 if (IDVal == ".sbss") {
7164 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
7165 return false;
7166 }
7167 if (IDVal == ".sdata") {
7168 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
7169 return false;
7170 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00007171
Rafael Espindola870c4e92012-01-11 03:56:41 +00007172 return true;
7173}
7174
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00007175bool MipsAsmParser::parseInternalDirectiveReallowModule() {
7176 // If this is not the end of the statement, report an error.
7177 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7178 reportParseError("unexpected token, expected end of statement");
7179 return false;
7180 }
7181
7182 getTargetStreamer().reallowModuleDirective();
7183
7184 getParser().Lex(); // Eat EndOfStatement token.
7185 return false;
7186}
7187
Rafael Espindola870c4e92012-01-11 03:56:41 +00007188extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00007189 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
7190 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
7191 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
7192 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00007193}
Jack Carterb4dbc172012-09-05 23:34:03 +00007194
7195#define GET_REGISTER_MATCHER
7196#define GET_MATCHER_IMPLEMENTATION
7197#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00007198
7199bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
7200 // Find the appropriate table for this asm variant.
7201 const MatchEntry *Start, *End;
7202 switch (VariantID) {
7203 default: llvm_unreachable("invalid variant!");
7204 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
7205 }
7206 // Search the table.
7207 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
7208 return MnemonicRange.first != MnemonicRange.second;
7209}