blob: 254175c05e152009058cf10d5af54d4e0e649d5e [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 Dardisaff4d142016-10-18 14:28:00 +0000279 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
280 const MCSubtargetInfo *STI, bool IsLoad);
281
Simon Dardis43115a12016-11-21 20:30:41 +0000282 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
283 const MCSubtargetInfo *STI);
284
285 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
286 const MCSubtargetInfo *STI);
287
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000288 bool reportParseError(Twine ErrorMsg);
289 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000290
Jack Carterb5cf5902013-04-17 00:18:04 +0000291 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000292
293 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000294 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000295 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000296 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000297 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000298 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000299 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000300 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000301 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000302 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000303 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000304 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000305 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000306 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000307
308 bool parseSetAtDirective();
309 bool parseSetNoAtDirective();
310 bool parseSetMacroDirective();
311 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000312 bool parseSetMsaDirective();
313 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000314 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000315 bool parseSetReorderDirective();
316 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000317 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000318 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000319 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000320 bool parseSetOddSPRegDirective();
321 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000322 bool parseSetPopDirective();
323 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000324 bool parseSetSoftFloatDirective();
325 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000326
Jack Carterd76b2372013-03-21 21:44:16 +0000327 bool parseSetAssignment();
328
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000329 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000330 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000331 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000332 bool parseDirectiveDtpRelWord();
333 bool parseDirectiveDtpRelDWord();
334 bool parseDirectiveTpRelWord();
335 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000336 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000337 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000338 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
339 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000340
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000341 bool parseInternalDirectiveReallowModule();
342
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000343 bool eatComma(StringRef ErrorStr);
344
Jack Carter1ac53222013-02-20 23:11:17 +0000345 int matchCPURegisterName(StringRef Symbol);
346
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000347 int matchHWRegsRegisterName(StringRef Symbol);
348
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000349 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000350
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000351 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000352
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000353 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000354
Jack Carter5dc8ac92013-09-25 23:50:44 +0000355 int matchMSA128RegisterName(StringRef Name);
356
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000357 int matchMSA128CtrlRegisterName(StringRef Name);
358
Jack Carterd0bd6422013-04-18 00:41:53 +0000359 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000360
Toma Tabacu89a712b2015-04-15 10:48:56 +0000361 /// Returns the internal register number for the current AT. Also checks if
362 /// the current AT is unavailable (set to $0) and gives an error if it is.
363 /// This should be used in pseudo-instruction expansions which need AT.
364 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000365
Simon Dardis3aa8a902017-02-06 12:43:46 +0000366 bool canUseATReg();
367
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000368 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
369 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000370
371 // Helper function that checks if the value of a vector index is within the
372 // boundaries of accepted values for each RegisterKind
373 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
374 bool validateMSAIndex(int Val, int RegKind);
375
Daniel Sandersf0df2212014-08-04 12:20:00 +0000376 // Selects a new architecture by updating the FeatureBits with the necessary
377 // info including implied dependencies.
378 // Internally, it clears all the feature bits related to *any* architecture
379 // and selects the new one using the ToggleFeature functionality of the
380 // MCSubtargetInfo object that handles implied dependencies. The reason we
381 // clear all the arch related bits manually is because ToggleFeature only
382 // clears the features that imply the feature being cleared and not the
383 // features implied by the feature being cleared. This is easier to see
384 // with an example:
385 // --------------------------------------------------
386 // | Feature | Implies |
387 // | -------------------------------------------------|
388 // | FeatureMips1 | None |
389 // | FeatureMips2 | FeatureMips1 |
390 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
391 // | FeatureMips4 | FeatureMips3 |
392 // | ... | |
393 // --------------------------------------------------
394 //
395 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
396 // FeatureMipsGP64 | FeatureMips1)
397 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
398 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000399 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000400 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000401 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
402 STI.setFeatureBits(FeatureBits);
403 setAvailableFeatures(
404 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000405 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000406 }
407
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000408 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000409 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000410 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000411 setAvailableFeatures(
412 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000413 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000414 }
415 }
416
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000417 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000418 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000419 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000420 setAvailableFeatures(
421 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000422 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000423 }
424 }
425
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000426 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
427 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000428 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000429 }
430
431 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
432 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000433 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000434 }
435
Rafael Espindola870c4e92012-01-11 03:56:41 +0000436public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000437 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000438 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000439 Match_RequiresDifferentOperands,
440 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000441 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000442 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000443 Match_NonZeroOperandForSync,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000444#define GET_OPERAND_DIAGNOSTIC_TYPES
445#include "MipsGenAsmMatcher.inc"
446#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000447 };
448
Akira Hatanakab11ef082015-11-14 06:35:56 +0000449 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000450 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000451 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000452 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
453 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000454 MCAsmParserExtension::Initialize(parser);
455
Toma Tabacu11e14a92015-04-21 11:50:52 +0000456 parser.addAliasForDirective(".asciiz", ".asciz");
457
Jack Carterb4dbc172012-09-05 23:34:03 +0000458 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000459 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000460
Toma Tabacu9db22db2014-09-09 10:15:38 +0000461 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000462 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000463 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000464
Toma Tabacu9db22db2014-09-09 10:15:38 +0000465 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000466 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000467 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000468
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000469 getTargetStreamer().updateABIInfo(*this);
470
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000471 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000472 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000473
474 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000475
Rafael Espindola699281c2016-05-18 11:58:50 +0000476 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000477
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000478 IsCpRestoreSet = false;
479 CpRestoreOffset = -1;
480
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000481 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000482 if ((TheTriple.getArch() == Triple::mips) ||
483 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000484 IsLittleEndian = false;
485 else
486 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000487 }
488
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000489 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
490 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
491
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000492 bool isGP64bit() const {
493 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
494 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000495
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000496 bool isFP64bit() const {
497 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
498 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000499
Eric Christophera5762812015-01-26 17:33:46 +0000500 const MipsABIInfo &getABI() const { return ABI; }
501 bool isABI_N32() const { return ABI.IsN32(); }
502 bool isABI_N64() const { return ABI.IsN64(); }
503 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000504 bool isABI_FPXX() const {
505 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
506 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000507
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000508 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000509 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000510 }
511
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000512 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000513 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000514 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000515
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000516 bool hasMips1() const {
517 return getSTI().getFeatureBits()[Mips::FeatureMips1];
518 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000519
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000520 bool hasMips2() const {
521 return getSTI().getFeatureBits()[Mips::FeatureMips2];
522 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000523
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000524 bool hasMips3() const {
525 return getSTI().getFeatureBits()[Mips::FeatureMips3];
526 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000527
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000528 bool hasMips4() const {
529 return getSTI().getFeatureBits()[Mips::FeatureMips4];
530 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000531
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000532 bool hasMips5() const {
533 return getSTI().getFeatureBits()[Mips::FeatureMips5];
534 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000535
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000536 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000537 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000538 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000539
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000540 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000541 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000542 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000543
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000544 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000545 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000546 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000547
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000548 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000549 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000550 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000551
Daniel Sanders17793142015-02-18 16:24:50 +0000552 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000553 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000554 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000555
Daniel Sanders17793142015-02-18 16:24:50 +0000556 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000557 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000558 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000559
Daniel Sanders17793142015-02-18 16:24:50 +0000560 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000561 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000562 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000563
Daniel Sanders17793142015-02-18 16:24:50 +0000564 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000565 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000566 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000567
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000568 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000569 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000570 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000571
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000572 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000573 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000574 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000575
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000576 bool hasDSP() const {
577 return getSTI().getFeatureBits()[Mips::FeatureDSP];
578 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000579
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000580 bool hasDSPR2() const {
581 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
582 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000583
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000584 bool hasDSPR3() const {
585 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
586 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000587
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000588 bool hasMSA() const {
589 return getSTI().getFeatureBits()[Mips::FeatureMSA];
590 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000591
Kai Nackee0245392015-01-27 19:11:28 +0000592 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000593 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000594 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000595
Daniel Sandersa6994442015-08-18 12:33:54 +0000596 bool inPicMode() {
597 return IsPicEnabled;
598 }
599
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000600 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000601 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000602 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000603
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000604 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000605 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000606 }
607
Eric Christophere8ae3e32015-05-07 23:10:21 +0000608 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000609 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000610 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000611
Toma Tabacud9d344b2015-04-27 14:05:04 +0000612 /// Warn if RegIndex is the same as the current AT.
613 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000614
615 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000616
617 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000618
619 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
620 AsmToken::TokenKind OperatorToken,
621 MCContext &Ctx) override {
622 switch(OperatorToken) {
623 default:
624 llvm_unreachable("Unknown token");
625 return nullptr;
626 case AsmToken::PercentCall16:
627 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
628 case AsmToken::PercentCall_Hi:
629 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
630 case AsmToken::PercentCall_Lo:
631 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
632 case AsmToken::PercentDtprel_Hi:
633 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
634 case AsmToken::PercentDtprel_Lo:
635 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
636 case AsmToken::PercentGot:
637 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
638 case AsmToken::PercentGot_Disp:
639 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
640 case AsmToken::PercentGot_Hi:
641 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
642 case AsmToken::PercentGot_Lo:
643 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
644 case AsmToken::PercentGot_Ofst:
645 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
646 case AsmToken::PercentGot_Page:
647 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
648 case AsmToken::PercentGottprel:
649 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
650 case AsmToken::PercentGp_Rel:
651 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
652 case AsmToken::PercentHi:
653 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
654 case AsmToken::PercentHigher:
655 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
656 case AsmToken::PercentHighest:
657 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
658 case AsmToken::PercentLo:
659 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
660 case AsmToken::PercentNeg:
661 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
662 case AsmToken::PercentPcrel_Hi:
663 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
664 case AsmToken::PercentPcrel_Lo:
665 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
666 case AsmToken::PercentTlsgd:
667 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
668 case AsmToken::PercentTlsldm:
669 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
670 case AsmToken::PercentTprel_Hi:
671 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
672 case AsmToken::PercentTprel_Lo:
673 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
674 }
675 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000676};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000677
678/// MipsOperand - Instances of this class represent a parsed Mips machine
679/// instruction.
680class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000681public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000682 /// Broad categories of register classes
683 /// The exact class is finalized by the render method.
684 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000685 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000686 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000687 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000688 RegKind_FCC = 4, /// FCC
689 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
690 RegKind_MSACtrl = 16, /// MSA control registers
691 RegKind_COP2 = 32, /// COP2
692 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
693 /// context).
694 RegKind_CCR = 128, /// CCR
695 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000696 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000697 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000698 /// Potentially any (e.g. $1)
699 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
700 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000701 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000702 };
703
704private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000705 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000706 k_Immediate, /// An immediate (possibly involving symbol references)
707 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000708 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000709 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000710 k_RegList, /// A physical register list
711 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000712 } Kind;
713
David Blaikie960ea3f2014-06-08 16:18:35 +0000714public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000715 MipsOperand(KindTy K, MipsAsmParser &Parser)
716 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
717
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000718 ~MipsOperand() override {
719 switch (Kind) {
720 case k_Immediate:
721 break;
722 case k_Memory:
723 delete Mem.Base;
724 break;
725 case k_RegList:
726 delete RegList.List;
727 case k_RegisterIndex:
728 case k_Token:
729 case k_RegPair:
730 break;
731 }
732 }
733
David Blaikie960ea3f2014-06-08 16:18:35 +0000734private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000735 /// For diagnostics, and checking the assembler temporary
736 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000737
Eric Christopher8996c5d2013-03-15 00:42:55 +0000738 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000739 const char *Data;
740 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000741 };
742
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000743 struct RegIdxOp {
744 unsigned Index; /// Index into the register class
745 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000746 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000747 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000748 };
749
750 struct ImmOp {
751 const MCExpr *Val;
752 };
753
754 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000755 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000756 const MCExpr *Off;
757 };
758
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000759 struct RegListOp {
760 SmallVector<unsigned, 10> *List;
761 };
762
Jack Carterb4dbc172012-09-05 23:34:03 +0000763 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000764 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000765 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000766 struct ImmOp Imm;
767 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000768 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000769 };
770
771 SMLoc StartLoc, EndLoc;
772
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000773 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000774 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
775 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000776 const MCRegisterInfo *RegInfo,
777 SMLoc S, SMLoc E,
778 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000779 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000780 Op->RegIdx.Index = Index;
781 Op->RegIdx.RegInfo = RegInfo;
782 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000783 Op->RegIdx.Tok.Data = Str.data();
784 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 Op->StartLoc = S;
786 Op->EndLoc = E;
787 return Op;
788 }
789
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000790public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000791 /// Coerce the register to GPR32 and return the real register for the current
792 /// target.
793 unsigned getGPR32Reg() const {
794 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000795 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000796 unsigned ClassID = Mips::GPR32RegClassID;
797 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000798 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000799
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000800 /// Coerce the register to GPR32 and return the real register for the current
801 /// target.
802 unsigned getGPRMM16Reg() const {
803 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
804 unsigned ClassID = Mips::GPR32RegClassID;
805 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
806 }
807
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000808 /// Coerce the register to GPR64 and return the real register for the current
809 /// target.
810 unsigned getGPR64Reg() const {
811 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
812 unsigned ClassID = Mips::GPR64RegClassID;
813 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000814 }
815
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000816private:
817 /// Coerce the register to AFGR64 and return the real register for the current
818 /// target.
819 unsigned getAFGR64Reg() const {
820 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
821 if (RegIdx.Index % 2 != 0)
822 AsmParser.Warning(StartLoc, "Float register should be even.");
823 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
824 .getRegister(RegIdx.Index / 2);
825 }
826
827 /// Coerce the register to FGR64 and return the real register for the current
828 /// target.
829 unsigned getFGR64Reg() const {
830 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
831 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
832 .getRegister(RegIdx.Index);
833 }
834
835 /// Coerce the register to FGR32 and return the real register for the current
836 /// target.
837 unsigned getFGR32Reg() const {
838 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
839 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
840 .getRegister(RegIdx.Index);
841 }
842
843 /// Coerce the register to FGRH32 and return the real register for the current
844 /// target.
845 unsigned getFGRH32Reg() const {
846 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
847 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
848 .getRegister(RegIdx.Index);
849 }
850
851 /// Coerce the register to FCC and return the real register for the current
852 /// target.
853 unsigned getFCCReg() const {
854 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
855 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
856 .getRegister(RegIdx.Index);
857 }
858
859 /// Coerce the register to MSA128 and return the real register for the current
860 /// target.
861 unsigned getMSA128Reg() const {
862 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
863 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
864 // identical
865 unsigned ClassID = Mips::MSA128BRegClassID;
866 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
867 }
868
869 /// Coerce the register to MSACtrl and return the real register for the
870 /// current target.
871 unsigned getMSACtrlReg() const {
872 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
873 unsigned ClassID = Mips::MSACtrlRegClassID;
874 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
875 }
876
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000877 /// Coerce the register to COP0 and return the real register for the
878 /// current target.
879 unsigned getCOP0Reg() const {
880 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
881 unsigned ClassID = Mips::COP0RegClassID;
882 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
883 }
884
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000885 /// Coerce the register to COP2 and return the real register for the
886 /// current target.
887 unsigned getCOP2Reg() const {
888 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
889 unsigned ClassID = Mips::COP2RegClassID;
890 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
891 }
892
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000893 /// Coerce the register to COP3 and return the real register for the
894 /// current target.
895 unsigned getCOP3Reg() const {
896 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
897 unsigned ClassID = Mips::COP3RegClassID;
898 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
899 }
900
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000901 /// Coerce the register to ACC64DSP and return the real register for the
902 /// current target.
903 unsigned getACC64DSPReg() const {
904 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
905 unsigned ClassID = Mips::ACC64DSPRegClassID;
906 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
907 }
908
909 /// Coerce the register to HI32DSP and return the real register for the
910 /// current target.
911 unsigned getHI32DSPReg() const {
912 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
913 unsigned ClassID = Mips::HI32DSPRegClassID;
914 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
915 }
916
917 /// Coerce the register to LO32DSP and return the real register for the
918 /// current target.
919 unsigned getLO32DSPReg() const {
920 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
921 unsigned ClassID = Mips::LO32DSPRegClassID;
922 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
923 }
924
925 /// Coerce the register to CCR and return the real register for the
926 /// current target.
927 unsigned getCCRReg() const {
928 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
929 unsigned ClassID = Mips::CCRRegClassID;
930 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
931 }
932
933 /// Coerce the register to HWRegs and return the real register for the
934 /// current target.
935 unsigned getHWRegsReg() const {
936 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
937 unsigned ClassID = Mips::HWRegsRegClassID;
938 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
939 }
940
941public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000942 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000943 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000944 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000945 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000946 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000947 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000948 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000949 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000950 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000951
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000952 void addRegOperands(MCInst &Inst, unsigned N) const {
953 llvm_unreachable("Use a custom parser instead");
954 }
955
Daniel Sanders21bce302014-04-01 12:35:23 +0000956 /// Render the operand to an MCInst as a GPR32
957 /// Asserts if the wrong number of operands are requested, or the operand
958 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000959 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
960 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000961 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000962 }
963
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000964 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
965 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000966 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000967 }
968
Jozef Kolek1904fa22014-11-24 14:25:53 +0000969 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
970 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000971 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000972 }
973
Zoran Jovanovic41688672015-02-10 16:36:20 +0000974 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
975 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000976 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000977 }
978
Daniel Sanders21bce302014-04-01 12:35:23 +0000979 /// Render the operand to an MCInst as a GPR64
980 /// Asserts if the wrong number of operands are requested, or the operand
981 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000982 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
983 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000984 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000985 }
986
987 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
988 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000989 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000990 }
991
992 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
993 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000994 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000995 }
996
997 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
998 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000999 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001000 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001001 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001002 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001003 AsmParser.getParser().printError(
1004 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1005 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001006 }
1007
1008 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1009 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001010 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001011 }
1012
1013 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1014 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001015 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001016 }
1017
1018 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1019 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001020 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001021 }
1022
1023 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1024 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001025 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001026 }
1027
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001028 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1029 assert(N == 1 && "Invalid number of operands!");
1030 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1031 }
1032
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001033 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1034 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001035 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001036 }
1037
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001038 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1039 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001040 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001041 }
1042
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001043 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1044 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001045 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001046 }
1047
1048 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1049 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001050 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001051 }
1052
1053 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1054 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001055 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001056 }
1057
1058 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1059 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001060 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001061 }
1062
1063 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1064 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001065 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001066 }
1067
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001068 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001069 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1070 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001071 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001072 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001073 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001074 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001075 Inst.addOperand(MCOperand::createImm(Imm));
1076 }
1077
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001078 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001079 void addSImmOperands(MCInst &Inst, unsigned N) const {
1080 if (isImm() && !isConstantImm()) {
1081 addExpr(Inst, getImm());
1082 return;
1083 }
1084 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1085 }
1086
1087 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001088 void addUImmOperands(MCInst &Inst, unsigned N) const {
1089 if (isImm() && !isConstantImm()) {
1090 addExpr(Inst, getImm());
1091 return;
1092 }
1093 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1094 }
1095
Daniel Sanders78e89022016-03-11 11:37:50 +00001096 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1097 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1098 assert(N == 1 && "Invalid number of operands!");
1099 int64_t Imm = getConstantImm() - Offset;
1100 Imm = SignExtend64<Bits>(Imm);
1101 Imm += Offset;
1102 Imm += AdjustOffset;
1103 Inst.addOperand(MCOperand::createImm(Imm));
1104 }
1105
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001106 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001107 assert(N == 1 && "Invalid number of operands!");
1108 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001109 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001110 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001111
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001112 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001113 assert(N == 2 && "Invalid number of operands!");
1114
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001115 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1116 ? getMemBase()->getGPR64Reg()
1117 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001118
1119 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001120 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001121 }
1122
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001123 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1124 assert(N == 2 && "Invalid number of operands!");
1125
Jim Grosbache9119e42015-05-13 18:37:00 +00001126 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001127
1128 const MCExpr *Expr = getMemOff();
1129 addExpr(Inst, Expr);
1130 }
1131
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001132 void addRegListOperands(MCInst &Inst, unsigned N) const {
1133 assert(N == 1 && "Invalid number of operands!");
1134
1135 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001136 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001137 }
1138
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001139 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1140 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001141 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001142 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001143 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1144 Inst.addOperand(MCOperand::createReg(
1145 RegIdx.RegInfo->getRegClass(
1146 AsmParser.getABI().AreGprs64bit()
1147 ? Mips::GPR64RegClassID
1148 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1149 Inst.addOperand(MCOperand::createReg(
1150 RegIdx.RegInfo->getRegClass(
1151 AsmParser.getABI().AreGprs64bit()
1152 ? Mips::GPR64RegClassID
1153 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001154 }
1155
Zoran Jovanovic41688672015-02-10 16:36:20 +00001156 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1157 assert(N == 2 && "Invalid number of operands!");
1158 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001159 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001160 }
1161
Craig Topper56c590a2014-04-29 07:58:02 +00001162 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001163 // As a special case until we sort out the definition of div/divu, accept
1164 // $0/$zero here so that MCK_ZERO works correctly.
1165 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001166 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001167
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001168 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001169 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001170
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001171 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001172 int64_t Res;
1173 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001174 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001175
Daniel Sanders52da7af2015-11-06 12:11:03 +00001176 bool isConstantImmz() const {
1177 return isConstantImm() && getConstantImm() == 0;
1178 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001179
Daniel Sandersea4f6532015-11-06 12:22:31 +00001180 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1181 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1182 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001183
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001184 template <unsigned Bits> bool isSImm() const {
1185 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1186 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001187
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001188 template <unsigned Bits> bool isUImm() const {
1189 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1190 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001191
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001192 template <unsigned Bits> bool isAnyImm() const {
1193 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1194 isUInt<Bits>(getConstantImm()))
1195 : isImm();
1196 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001197
Daniel Sanders78e89022016-03-11 11:37:50 +00001198 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1199 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001200 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001201
Hrvoje Varga46458d02016-02-25 12:53:29 +00001202 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1203 return isConstantImm() && getConstantImm() >= Bottom &&
1204 getConstantImm() <= Top;
1205 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001206
Craig Topper56c590a2014-04-29 07:58:02 +00001207 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001208 // Note: It's not possible to pretend that other operand kinds are tokens.
1209 // The matcher emitter checks tokens first.
1210 return Kind == k_Token;
1211 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001212
Craig Topper56c590a2014-04-29 07:58:02 +00001213 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001214
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001215 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001216 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001217 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001218
Simon Dardis4ccda502016-05-27 13:56:36 +00001219 // Allow relocation operators.
1220 // FIXME: This predicate and others need to look through binary expressions
1221 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001222 template <unsigned Bits, unsigned ShiftAmount = 0>
1223 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001224 if (!isMem())
1225 return false;
1226 if (!getMemBase()->isGPRAsmReg())
1227 return false;
1228 if (isa<MCTargetExpr>(getMemOff()) ||
1229 (isConstantMemOff() &&
1230 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1231 return true;
1232 MCValue Res;
1233 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1234 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001235 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001236
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001237 bool isMemWithGRPMM16Base() const {
1238 return isMem() && getMemBase()->isMM16AsmReg();
1239 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001240
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001241 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1242 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1243 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1244 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001245
Jozef Kolek12c69822014-12-23 16:16:33 +00001246 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1247 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1248 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1249 && (getMemBase()->getGPR32Reg() == Mips::SP);
1250 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001251
Daniel Sanderse473dc92016-05-09 13:38:25 +00001252 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1253 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1254 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1255 && (getMemBase()->getGPR32Reg() == Mips::GP);
1256 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001257
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001258 template <unsigned Bits, unsigned ShiftLeftAmount>
1259 bool isScaledUImm() const {
1260 return isConstantImm() &&
1261 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001262 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001263
Daniel Sanders97297772016-03-22 14:40:00 +00001264 template <unsigned Bits, unsigned ShiftLeftAmount>
1265 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001266 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1267 return true;
1268 // Operand can also be a symbol or symbol plus offset in case of relocations.
1269 if (Kind != k_Immediate)
1270 return false;
1271 MCValue Res;
1272 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1273 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001274 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001275
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001276 bool isRegList16() const {
1277 if (!isRegList())
1278 return false;
1279
1280 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001281 if (Size < 2 || Size > 5)
1282 return false;
1283
1284 unsigned R0 = RegList.List->front();
1285 unsigned R1 = RegList.List->back();
1286 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1287 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001288 return false;
1289
1290 int PrevReg = *RegList.List->begin();
1291 for (int i = 1; i < Size - 1; i++) {
1292 int Reg = (*(RegList.List))[i];
1293 if ( Reg != PrevReg + 1)
1294 return false;
1295 PrevReg = Reg;
1296 }
1297
1298 return true;
1299 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001300
Vladimir Medic2b953d02013-10-01 09:48:56 +00001301 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001302
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001303 bool isLSAImm() const {
1304 if (!isConstantImm())
1305 return false;
1306 int64_t Val = getConstantImm();
1307 return 1 <= Val && Val <= 4;
1308 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001309
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001310 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001311
Zoran Jovanovic41688672015-02-10 16:36:20 +00001312 bool isMovePRegPair() const {
1313 if (Kind != k_RegList || RegList.List->size() != 2)
1314 return false;
1315
1316 unsigned R0 = RegList.List->front();
1317 unsigned R1 = RegList.List->back();
1318
1319 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1320 (R0 == Mips::A1 && R1 == Mips::A3) ||
1321 (R0 == Mips::A2 && R1 == Mips::A3) ||
1322 (R0 == Mips::A0 && R1 == Mips::S5) ||
1323 (R0 == Mips::A0 && R1 == Mips::S6) ||
1324 (R0 == Mips::A0 && R1 == Mips::A1) ||
1325 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001326 (R0 == Mips::A0 && R1 == Mips::A3) ||
1327 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1328 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1329 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1330 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1331 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1332 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1333 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1334 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001335 return true;
1336
1337 return false;
1338 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001339
1340 StringRef getToken() const {
1341 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001342 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001343 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001344
Zlatko Buljanba553a62016-05-09 08:07:28 +00001345 bool isRegPair() const {
1346 return Kind == k_RegPair && RegIdx.Index <= 30;
1347 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001348
Craig Topper56c590a2014-04-29 07:58:02 +00001349 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001350 // As a special case until we sort out the definition of div/divu, accept
1351 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001352 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1353 RegIdx.Kind & RegKind_GPR)
1354 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001355
Daniel Sanders976d9382016-07-05 13:38:40 +00001356 llvm_unreachable("Invalid access!");
1357 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001358 }
1359
Jack Carterb4dbc172012-09-05 23:34:03 +00001360 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001361 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001362 return Imm.Val;
1363 }
1364
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001365 int64_t getConstantImm() const {
1366 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001367 int64_t Value = 0;
1368 (void)Val->evaluateAsAbsolute(Value);
1369 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001370 }
1371
1372 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001373 assert((Kind == k_Memory) && "Invalid access!");
1374 return Mem.Base;
1375 }
1376
1377 const MCExpr *getMemOff() const {
1378 assert((Kind == k_Memory) && "Invalid access!");
1379 return Mem.Off;
1380 }
1381
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001382 int64_t getConstantMemOff() const {
1383 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1384 }
1385
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001386 const SmallVectorImpl<unsigned> &getRegList() const {
1387 assert((Kind == k_RegList) && "Invalid access!");
1388 return *(RegList.List);
1389 }
1390
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001391 unsigned getRegPair() const {
1392 assert((Kind == k_RegPair) && "Invalid access!");
1393 return RegIdx.Index;
1394 }
1395
David Blaikie960ea3f2014-06-08 16:18:35 +00001396 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1397 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001398 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001399 Op->Tok.Data = Str.data();
1400 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001401 Op->StartLoc = S;
1402 Op->EndLoc = S;
1403 return Op;
1404 }
1405
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001406 /// Create a numeric register (e.g. $1). The exact register remains
1407 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001408 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001409 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1410 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001411 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001412 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001413 }
1414
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001415 /// Create a register that is definitely a GPR.
1416 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001417 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001418 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1419 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1420 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001421 }
1422
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001423 /// Create a register that is definitely a FGR.
1424 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001425 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001426 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1427 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1428 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001429 }
1430
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001431 /// Create a register that is definitely a HWReg.
1432 /// This is typically only used for named registers such as $hwr_cpunum.
1433 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001434 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001435 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001436 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001437 }
1438
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001439 /// Create a register that is definitely an FCC.
1440 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001441 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001442 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1443 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1444 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001445 }
1446
1447 /// Create a register that is definitely an ACC.
1448 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001449 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001450 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1451 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1452 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001453 }
1454
1455 /// Create a register that is definitely an MSA128.
1456 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001457 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001458 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1459 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1460 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001461 }
1462
1463 /// Create a register that is definitely an MSACtrl.
1464 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001465 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001466 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1467 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1468 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001469 }
1470
David Blaikie960ea3f2014-06-08 16:18:35 +00001471 static std::unique_ptr<MipsOperand>
1472 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001473 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001474 Op->Imm.Val = Val;
1475 Op->StartLoc = S;
1476 Op->EndLoc = E;
1477 return Op;
1478 }
1479
David Blaikie960ea3f2014-06-08 16:18:35 +00001480 static std::unique_ptr<MipsOperand>
1481 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1482 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001483 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001484 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001485 Op->Mem.Off = Off;
1486 Op->StartLoc = S;
1487 Op->EndLoc = E;
1488 return Op;
1489 }
1490
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001491 static std::unique_ptr<MipsOperand>
1492 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1493 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001494 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001495
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001496 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001497 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001498 Op->StartLoc = StartLoc;
1499 Op->EndLoc = EndLoc;
1500 return Op;
1501 }
1502
Daniel Sandersd044e492016-05-09 13:10:57 +00001503 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1504 SMLoc S, SMLoc E,
1505 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001506 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001507 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001508 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1509 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001510 Op->StartLoc = S;
1511 Op->EndLoc = E;
1512 return Op;
1513 }
1514
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001515 bool isGPRAsmReg() const {
1516 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001517 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001518
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001519 bool isMM16AsmReg() const {
1520 if (!(isRegIdx() && RegIdx.Kind))
1521 return false;
1522 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1523 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001524
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001525 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001526 bool isMM16AsmRegZero() const {
1527 if (!(isRegIdx() && RegIdx.Kind))
1528 return false;
1529 return (RegIdx.Index == 0 ||
1530 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1531 RegIdx.Index == 17);
1532 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001533
Zoran Jovanovic41688672015-02-10 16:36:20 +00001534 bool isMM16AsmRegMoveP() const {
1535 if (!(isRegIdx() && RegIdx.Kind))
1536 return false;
1537 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1538 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1539 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001540
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001541 bool isFGRAsmReg() const {
1542 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1543 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001544 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001545
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001546 bool isHWRegsAsmReg() const {
1547 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001548 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001549
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001550 bool isCCRAsmReg() const {
1551 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001552 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001553
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001554 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001555 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1556 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001557 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001558 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001559
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001560 bool isACCAsmReg() const {
1561 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001562 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001563
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001564 bool isCOP0AsmReg() const {
1565 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1566 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001567
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001568 bool isCOP2AsmReg() const {
1569 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001570 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001571
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001572 bool isCOP3AsmReg() const {
1573 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1574 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001575
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001576 bool isMSA128AsmReg() const {
1577 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001578 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001579
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001580 bool isMSACtrlAsmReg() const {
1581 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001582 }
1583
Jack Carterb4dbc172012-09-05 23:34:03 +00001584 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001585 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001586 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001587 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001588
Craig Topper56c590a2014-04-29 07:58:02 +00001589 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001590 switch (Kind) {
1591 case k_Immediate:
1592 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001593 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001594 OS << ">";
1595 break;
1596 case k_Memory:
1597 OS << "Mem<";
1598 Mem.Base->print(OS);
1599 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001600 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001601 OS << ">";
1602 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001603 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001604 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1605 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001606 break;
1607 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001608 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001609 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001610 case k_RegList:
1611 OS << "RegList< ";
1612 for (auto Reg : (*RegList.List))
1613 OS << Reg << " ";
1614 OS << ">";
1615 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001616 case k_RegPair:
1617 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1618 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001619 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001620 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001621
1622 bool isValidForTie(const MipsOperand &Other) const {
1623 if (Kind != Other.Kind)
1624 return false;
1625
1626 switch (Kind) {
1627 default:
1628 llvm_unreachable("Unexpected kind");
1629 return false;
1630 case k_RegisterIndex: {
1631 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1632 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1633 return Token == OtherToken;
1634 }
1635 }
1636 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001637}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001638
1639} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001640
Jack Carter9e65aa32013-03-22 00:05:30 +00001641namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001642
Jack Carter9e65aa32013-03-22 00:05:30 +00001643extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001644
1645} // end namespace llvm
1646
Jack Carter9e65aa32013-03-22 00:05:30 +00001647static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1648 return MipsInsts[Opcode];
1649}
1650
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001651static bool hasShortDelaySlot(unsigned Opcode) {
1652 switch (Opcode) {
1653 case Mips::JALS_MM:
1654 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001655 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001656 case Mips::BGEZALS_MM:
1657 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001658 return true;
1659 default:
1660 return false;
1661 }
1662}
1663
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001664static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1665 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1666 return &SRExpr->getSymbol();
1667 }
1668
1669 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1670 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1671 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1672
1673 if (LHSSym)
1674 return LHSSym;
1675
1676 if (RHSSym)
1677 return RHSSym;
1678
1679 return nullptr;
1680 }
1681
1682 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1683 return getSingleMCSymbol(UExpr->getSubExpr());
1684
1685 return nullptr;
1686}
1687
1688static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1689 if (isa<MCSymbolRefExpr>(Expr))
1690 return 1;
1691
1692 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1693 return countMCSymbolRefExpr(BExpr->getLHS()) +
1694 countMCSymbolRefExpr(BExpr->getRHS());
1695
1696 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1697 return countMCSymbolRefExpr(UExpr->getSubExpr());
1698
1699 return 0;
1700}
1701
Jack Carter9e65aa32013-03-22 00:05:30 +00001702bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001703 MCStreamer &Out,
1704 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001705 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001706 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001707 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001708
Jack Carter9e65aa32013-03-22 00:05:30 +00001709 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001710
1711 if (MCID.isBranch() || MCID.isCall()) {
1712 const unsigned Opcode = Inst.getOpcode();
1713 MCOperand Offset;
1714
1715 switch (Opcode) {
1716 default:
1717 break;
Kai Nackee0245392015-01-27 19:11:28 +00001718 case Mips::BBIT0:
1719 case Mips::BBIT032:
1720 case Mips::BBIT1:
1721 case Mips::BBIT132:
1722 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001723 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001724
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001725 case Mips::BEQ:
1726 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001727 case Mips::BEQ_MM:
1728 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001729 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001730 Offset = Inst.getOperand(2);
1731 if (!Offset.isImm())
1732 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001733 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001734 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001735 if (OffsetToAlignment(Offset.getImm(),
1736 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001737 return Error(IDLoc, "branch to misaligned address");
1738 break;
1739 case Mips::BGEZ:
1740 case Mips::BGTZ:
1741 case Mips::BLEZ:
1742 case Mips::BLTZ:
1743 case Mips::BGEZAL:
1744 case Mips::BLTZAL:
1745 case Mips::BC1F:
1746 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001747 case Mips::BGEZ_MM:
1748 case Mips::BGTZ_MM:
1749 case Mips::BLEZ_MM:
1750 case Mips::BLTZ_MM:
1751 case Mips::BGEZAL_MM:
1752 case Mips::BLTZAL_MM:
1753 case Mips::BC1F_MM:
1754 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001755 case Mips::BC1EQZC_MMR6:
1756 case Mips::BC1NEZC_MMR6:
1757 case Mips::BC2EQZC_MMR6:
1758 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001759 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001760 Offset = Inst.getOperand(1);
1761 if (!Offset.isImm())
1762 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001763 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001764 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001765 if (OffsetToAlignment(Offset.getImm(),
1766 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001767 return Error(IDLoc, "branch to misaligned address");
1768 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001769 case Mips::BGEC: case Mips::BGEC_MMR6:
1770 case Mips::BLTC: case Mips::BLTC_MMR6:
1771 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1772 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1773 case Mips::BEQC: case Mips::BEQC_MMR6:
1774 case Mips::BNEC: case Mips::BNEC_MMR6:
1775 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1776 Offset = Inst.getOperand(2);
1777 if (!Offset.isImm())
1778 break; // We'll deal with this situation later on when applying fixups.
1779 if (!isIntN(18, Offset.getImm()))
1780 return Error(IDLoc, "branch target out of range");
1781 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1782 return Error(IDLoc, "branch to misaligned address");
1783 break;
1784 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1785 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1786 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1787 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1788 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1789 Offset = Inst.getOperand(1);
1790 if (!Offset.isImm())
1791 break; // We'll deal with this situation later on when applying fixups.
1792 if (!isIntN(18, Offset.getImm()))
1793 return Error(IDLoc, "branch target out of range");
1794 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1795 return Error(IDLoc, "branch to misaligned address");
1796 break;
1797 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1798 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1799 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1800 Offset = Inst.getOperand(1);
1801 if (!Offset.isImm())
1802 break; // We'll deal with this situation later on when applying fixups.
1803 if (!isIntN(23, Offset.getImm()))
1804 return Error(IDLoc, "branch target out of range");
1805 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1806 return Error(IDLoc, "branch to misaligned address");
1807 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001808 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001809 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001810 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001811 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001812 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1813 Offset = Inst.getOperand(1);
1814 if (!Offset.isImm())
1815 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001816 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001817 return Error(IDLoc, "branch target out of range");
1818 if (OffsetToAlignment(Offset.getImm(), 2LL))
1819 return Error(IDLoc, "branch to misaligned address");
1820 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001821 }
1822 }
1823
Daniel Sandersa84989a2014-06-16 13:25:35 +00001824 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1825 // We still accept it but it is a normal nop.
1826 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1827 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1828 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1829 "nop instruction");
1830 }
1831
Kai Nackee0245392015-01-27 19:11:28 +00001832 if (hasCnMips()) {
1833 const unsigned Opcode = Inst.getOpcode();
1834 MCOperand Opnd;
1835 int Imm;
1836
1837 switch (Opcode) {
1838 default:
1839 break;
1840
1841 case Mips::BBIT0:
1842 case Mips::BBIT032:
1843 case Mips::BBIT1:
1844 case Mips::BBIT132:
1845 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1846 // The offset is handled above
1847 Opnd = Inst.getOperand(1);
1848 if (!Opnd.isImm())
1849 return Error(IDLoc, "expected immediate operand kind");
1850 Imm = Opnd.getImm();
1851 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1852 Opcode == Mips::BBIT1 ? 63 : 31))
1853 return Error(IDLoc, "immediate operand value out of range");
1854 if (Imm > 31) {
1855 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1856 : Mips::BBIT132);
1857 Inst.getOperand(1).setImm(Imm - 32);
1858 }
1859 break;
1860
Kai Nackee0245392015-01-27 19:11:28 +00001861 case Mips::SEQi:
1862 case Mips::SNEi:
1863 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1864 Opnd = Inst.getOperand(2);
1865 if (!Opnd.isImm())
1866 return Error(IDLoc, "expected immediate operand kind");
1867 Imm = Opnd.getImm();
1868 if (!isInt<10>(Imm))
1869 return Error(IDLoc, "immediate operand value out of range");
1870 break;
1871 }
1872 }
1873
Simon Atanasyan50485142016-12-12 17:40:26 +00001874 // For PIC code convert unconditional jump to unconditional branch.
1875 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
1876 inPicMode()) {
1877 MCInst BInst;
1878 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
1879 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1880 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1881 BInst.addOperand(Inst.getOperand(0));
1882 Inst = BInst;
1883 }
1884
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001885 // This expansion is not in a function called by tryExpandInstruction()
1886 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001887 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1888 inPicMode()) {
1889 warnIfNoMacro(IDLoc);
1890
1891 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1892
1893 // We can do this expansion if there's only 1 symbol in the argument
1894 // expression.
1895 if (countMCSymbolRefExpr(JalExpr) > 1)
1896 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1897
1898 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001899 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001900 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1901
1902 // FIXME: Add support for label+offset operands (currently causes an error).
1903 // FIXME: Add support for forward-declared local symbols.
1904 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00001905 if (JalSym->isInSection() || JalSym->isTemporary() ||
1906 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001907 if (isABI_O32()) {
1908 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001909 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001910 // R_(MICRO)MIPS_GOT16 label
1911 // addiu $25, $25, 0
1912 // R_(MICRO)MIPS_LO16 label
1913 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001914 const MCExpr *Got16RelocExpr =
1915 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1916 const MCExpr *Lo16RelocExpr =
1917 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001918
Daniel Sandersa736b372016-04-29 13:33:12 +00001919 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1920 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1921 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1922 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001923 } else if (isABI_N32() || isABI_N64()) {
1924 // If it's a local symbol and the N32/N64 ABIs are being used,
1925 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001926 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001927 // R_(MICRO)MIPS_GOT_DISP label
1928 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001929 const MCExpr *GotDispRelocExpr =
1930 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001931
Daniel Sandersa736b372016-04-29 13:33:12 +00001932 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1933 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1934 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001935 }
1936 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001937 // If it's an external/weak symbol, we expand to:
1938 // lw/ld $25, 0($gp)
1939 // R_(MICRO)MIPS_CALL16 label
1940 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001941 const MCExpr *Call16RelocExpr =
1942 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001943
Daniel Sandersa736b372016-04-29 13:33:12 +00001944 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1945 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001946 }
1947
1948 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001949 if (IsCpRestoreSet && inMicroMipsMode())
1950 JalrInst.setOpcode(Mips::JALRS_MM);
1951 else
1952 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001953 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1954 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1955
1956 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1957 // This relocation is supposed to be an optimization hint for the linker
1958 // and is not necessary for correctness.
1959
1960 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001961 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001962 }
1963
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001964 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
1965 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001966 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001967 // reference or immediate we may have to expand instructions.
1968 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001969 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001970 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1971 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001972 MCOperand &Op = Inst.getOperand(i);
1973 if (Op.isImm()) {
1974 int MemOffset = Op.getImm();
1975 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001976 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001977 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00001978 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001979 }
1980 } else if (Op.isExpr()) {
1981 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001982 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001983 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001984 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001985 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001986 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001987 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00001988 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001989 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001990 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001991 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00001992 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001993 }
1994 }
1995 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001996 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001997 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001998
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001999 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002000 if (MCID.mayLoad()) {
2001 // Try to create 16-bit GP relative load instruction.
2002 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2003 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2004 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2005 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2006 MCOperand &Op = Inst.getOperand(i);
2007 if (Op.isImm()) {
2008 int MemOffset = Op.getImm();
2009 MCOperand &DstReg = Inst.getOperand(0);
2010 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002011 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002012 getContext().getRegisterInfo()->getRegClass(
2013 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002014 (BaseReg.getReg() == Mips::GP ||
2015 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002016
Daniel Sandersa736b372016-04-29 13:33:12 +00002017 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2018 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002019 return false;
2020 }
2021 }
2022 }
2023 } // for
2024 } // if load
2025
2026 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2027
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002028 MCOperand Opnd;
2029 int Imm;
2030
2031 switch (Inst.getOpcode()) {
2032 default:
2033 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002034 case Mips::ADDIUSP_MM:
2035 Opnd = Inst.getOperand(0);
2036 if (!Opnd.isImm())
2037 return Error(IDLoc, "expected immediate operand kind");
2038 Imm = Opnd.getImm();
2039 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2040 Imm % 4 != 0)
2041 return Error(IDLoc, "immediate operand value out of range");
2042 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002043 case Mips::SLL16_MM:
2044 case Mips::SRL16_MM:
2045 Opnd = Inst.getOperand(2);
2046 if (!Opnd.isImm())
2047 return Error(IDLoc, "expected immediate operand kind");
2048 Imm = Opnd.getImm();
2049 if (Imm < 1 || Imm > 8)
2050 return Error(IDLoc, "immediate operand value out of range");
2051 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002052 case Mips::LI16_MM:
2053 Opnd = Inst.getOperand(1);
2054 if (!Opnd.isImm())
2055 return Error(IDLoc, "expected immediate operand kind");
2056 Imm = Opnd.getImm();
2057 if (Imm < -1 || Imm > 126)
2058 return Error(IDLoc, "immediate operand value out of range");
2059 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002060 case Mips::ADDIUR2_MM:
2061 Opnd = Inst.getOperand(2);
2062 if (!Opnd.isImm())
2063 return Error(IDLoc, "expected immediate operand kind");
2064 Imm = Opnd.getImm();
2065 if (!(Imm == 1 || Imm == -1 ||
2066 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2067 return Error(IDLoc, "immediate operand value out of range");
2068 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002069 case Mips::ANDI16_MM:
2070 Opnd = Inst.getOperand(2);
2071 if (!Opnd.isImm())
2072 return Error(IDLoc, "expected immediate operand kind");
2073 Imm = Opnd.getImm();
2074 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2075 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2076 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2077 return Error(IDLoc, "immediate operand value out of range");
2078 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002079 case Mips::LBU16_MM:
2080 Opnd = Inst.getOperand(2);
2081 if (!Opnd.isImm())
2082 return Error(IDLoc, "expected immediate operand kind");
2083 Imm = Opnd.getImm();
2084 if (Imm < -1 || Imm > 14)
2085 return Error(IDLoc, "immediate operand value out of range");
2086 break;
2087 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002088 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002089 Opnd = Inst.getOperand(2);
2090 if (!Opnd.isImm())
2091 return Error(IDLoc, "expected immediate operand kind");
2092 Imm = Opnd.getImm();
2093 if (Imm < 0 || Imm > 15)
2094 return Error(IDLoc, "immediate operand value out of range");
2095 break;
2096 case Mips::LHU16_MM:
2097 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002098 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002099 Opnd = Inst.getOperand(2);
2100 if (!Opnd.isImm())
2101 return Error(IDLoc, "expected immediate operand kind");
2102 Imm = Opnd.getImm();
2103 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2104 return Error(IDLoc, "immediate operand value out of range");
2105 break;
2106 case Mips::LW16_MM:
2107 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002108 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002109 Opnd = Inst.getOperand(2);
2110 if (!Opnd.isImm())
2111 return Error(IDLoc, "expected immediate operand kind");
2112 Imm = Opnd.getImm();
2113 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2114 return Error(IDLoc, "immediate operand value out of range");
2115 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002116 case Mips::ADDIUPC_MM:
2117 MCOperand Opnd = Inst.getOperand(1);
2118 if (!Opnd.isImm())
2119 return Error(IDLoc, "expected immediate operand kind");
2120 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002121 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002122 return Error(IDLoc, "immediate operand value out of range");
2123 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002124 }
2125 }
2126
Daniel Sandersd8c07762016-04-18 12:35:36 +00002127 bool FillDelaySlot =
2128 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2129 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002130 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002131
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002132 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002133 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002134 switch (ExpandResult) {
2135 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002136 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002137 break;
2138 case MER_Success:
2139 break;
2140 case MER_Fail:
2141 return true;
2142 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002143
Daniel Sanderscda908a2016-05-16 09:10:13 +00002144 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2145 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2146 if (inMicroMipsMode())
2147 TOut.setUsesMicroMips();
2148
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002149 // If this instruction has a delay slot and .set reorder is active,
2150 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002151 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002152 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2153 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002154 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002155
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002156 if ((Inst.getOpcode() == Mips::JalOneReg ||
2157 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2158 isPicAndNotNxxAbi()) {
2159 if (IsCpRestoreSet) {
2160 // We need a NOP between the JALR and the LW:
2161 // If .set reorder has been used, we've already emitted a NOP.
2162 // If .set noreorder has been used, we need to emit a NOP at this point.
2163 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002164 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2165 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002166
2167 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002168 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002169 } else
2170 Warning(IDLoc, "no .cprestore used in PIC mode");
2171 }
2172
Jack Carter9e65aa32013-03-22 00:05:30 +00002173 return false;
2174}
2175
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002176MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002177MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2178 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002179 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002180 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002181 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002182 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002183 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002184 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002185 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002186 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002187 case Mips::LoadAddrImm64:
2188 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2189 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2190 "expected immediate operand kind");
2191
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002192 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2193 Inst.getOperand(1),
2194 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002195 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002196 ? MER_Fail
2197 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002198 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002199 case Mips::LoadAddrReg64:
2200 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2201 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2202 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2203 "expected immediate operand kind");
2204
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002205 return expandLoadAddress(Inst.getOperand(0).getReg(),
2206 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2207 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002208 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002209 ? MER_Fail
2210 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002211 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002212 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002213 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2214 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002215 case Mips::SWM_MM:
2216 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002217 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2218 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002219 case Mips::JalOneReg:
2220 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002221 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002222 case Mips::BneImm:
2223 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002224 case Mips::BEQLImmMacro:
2225 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002226 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002227 case Mips::BLT:
2228 case Mips::BLE:
2229 case Mips::BGE:
2230 case Mips::BGT:
2231 case Mips::BLTU:
2232 case Mips::BLEU:
2233 case Mips::BGEU:
2234 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002235 case Mips::BLTL:
2236 case Mips::BLEL:
2237 case Mips::BGEL:
2238 case Mips::BGTL:
2239 case Mips::BLTUL:
2240 case Mips::BLEUL:
2241 case Mips::BGEUL:
2242 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002243 case Mips::BLTImmMacro:
2244 case Mips::BLEImmMacro:
2245 case Mips::BGEImmMacro:
2246 case Mips::BGTImmMacro:
2247 case Mips::BLTUImmMacro:
2248 case Mips::BLEUImmMacro:
2249 case Mips::BGEUImmMacro:
2250 case Mips::BGTUImmMacro:
2251 case Mips::BLTLImmMacro:
2252 case Mips::BLELImmMacro:
2253 case Mips::BGELImmMacro:
2254 case Mips::BGTLImmMacro:
2255 case Mips::BLTULImmMacro:
2256 case Mips::BLEULImmMacro:
2257 case Mips::BGEULImmMacro:
2258 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002259 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002260 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002261 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002262 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2263 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002264 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002265 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002266 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2267 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002268 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002269 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002270 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2271 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002272 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002273 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002274 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2275 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002276 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002277 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2278 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002279 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002280 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002281 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002282 case Mips::PseudoTRUNC_W_D:
2283 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2284 : MER_Success;
2285 case Mips::Ulh:
2286 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2287 case Mips::Ulhu:
2288 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002289 case Mips::Ush:
2290 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002291 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002292 case Mips::Usw:
2293 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002294 case Mips::NORImm:
2295 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002296 case Mips::ADDi:
2297 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002298 case Mips::SLTi:
2299 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002300 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2301 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2302 int64_t ImmValue = Inst.getOperand(2).getImm();
2303 if (isInt<16>(ImmValue))
2304 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002305 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2306 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002307 }
2308 return MER_NotAMacro;
2309 case Mips::ANDi:
2310 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002311 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002312 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2313 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2314 int64_t ImmValue = Inst.getOperand(2).getImm();
2315 if (isUInt<16>(ImmValue))
2316 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002317 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2318 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002319 }
2320 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002321 case Mips::ROL:
2322 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002323 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002324 case Mips::ROLImm:
2325 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002326 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002327 case Mips::DROL:
2328 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002329 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002330 case Mips::DROLImm:
2331 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002332 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002333 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002334 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002335 case Mips::LDMacro:
2336 case Mips::SDMacro:
2337 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2338 Inst.getOpcode() == Mips::LDMacro)
2339 ? MER_Fail
2340 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002341 case Mips::SEQMacro:
2342 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2343 case Mips::SEQIMacro:
2344 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002345 }
Jack Carter30a59822012-10-04 04:03:53 +00002346}
Jack Carter92995f12012-10-06 00:53:28 +00002347
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002348bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002349 MCStreamer &Out,
2350 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002351 MipsTargetStreamer &TOut = getTargetStreamer();
2352
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002353 // Create a JALR instruction which is going to replace the pseudo-JAL.
2354 MCInst JalrInst;
2355 JalrInst.setLoc(IDLoc);
2356 const MCOperand FirstRegOp = Inst.getOperand(0);
2357 const unsigned Opcode = Inst.getOpcode();
2358
2359 if (Opcode == Mips::JalOneReg) {
2360 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002361 if (IsCpRestoreSet && inMicroMipsMode()) {
2362 JalrInst.setOpcode(Mips::JALRS16_MM);
2363 JalrInst.addOperand(FirstRegOp);
2364 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002365 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002366 JalrInst.addOperand(FirstRegOp);
2367 } else {
2368 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002369 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002370 JalrInst.addOperand(FirstRegOp);
2371 }
2372 } else if (Opcode == Mips::JalTwoReg) {
2373 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002374 if (IsCpRestoreSet && inMicroMipsMode())
2375 JalrInst.setOpcode(Mips::JALRS_MM);
2376 else
2377 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002378 JalrInst.addOperand(FirstRegOp);
2379 const MCOperand SecondRegOp = Inst.getOperand(1);
2380 JalrInst.addOperand(SecondRegOp);
2381 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002382 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002383
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002384 // If .set reorder is active and branch instruction has a delay slot,
2385 // emit a NOP after it.
2386 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002387 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2388 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2389 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002390
2391 return false;
2392}
2393
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002394/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002395template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002396 unsigned BitNum = findFirstSet(x);
2397
2398 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2399}
2400
2401/// Load (or add) an immediate into a register.
2402///
2403/// @param ImmValue The immediate to load.
2404/// @param DstReg The register that will hold the immediate.
2405/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2406/// for a simple initialization.
2407/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2408/// @param IsAddress True if the immediate represents an address. False if it
2409/// is an integer.
2410/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002411bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002412 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002413 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2414 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002415 MipsTargetStreamer &TOut = getTargetStreamer();
2416
Toma Tabacu00e98672015-05-01 12:19:27 +00002417 if (!Is32BitImm && !isGP64bit()) {
2418 Error(IDLoc, "instruction requires a 64-bit architecture");
2419 return true;
2420 }
2421
Daniel Sanders03f9c012015-07-14 12:24:22 +00002422 if (Is32BitImm) {
2423 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2424 // Sign extend up to 64-bit so that the predicates match the hardware
2425 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2426 // true.
2427 ImmValue = SignExtend64<32>(ImmValue);
2428 } else {
2429 Error(IDLoc, "instruction requires a 32-bit immediate");
2430 return true;
2431 }
2432 }
2433
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002434 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2435 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2436
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002437 bool UseSrcReg = false;
2438 if (SrcReg != Mips::NoRegister)
2439 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002440
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002441 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002442 if (UseSrcReg &&
2443 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002444 // At this point we need AT to perform the expansions and we exit if it is
2445 // not available.
2446 unsigned ATReg = getATReg(IDLoc);
2447 if (!ATReg)
2448 return true;
2449 TmpReg = ATReg;
2450 }
2451
Daniel Sanders03f9c012015-07-14 12:24:22 +00002452 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002453 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002454 SrcReg = ZeroReg;
2455
2456 // This doesn't quite follow the usual ABI expectations for N32 but matches
2457 // traditional assembler behaviour. N32 would normally use addiu for both
2458 // integers and addresses.
2459 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002460 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002461 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002462 }
2463
Daniel Sandersa736b372016-04-29 13:33:12 +00002464 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002465 return false;
2466 }
2467
2468 if (isUInt<16>(ImmValue)) {
2469 unsigned TmpReg = DstReg;
2470 if (SrcReg == DstReg) {
2471 TmpReg = getATReg(IDLoc);
2472 if (!TmpReg)
2473 return true;
2474 }
2475
Daniel Sandersa736b372016-04-29 13:33:12 +00002476 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002477 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002478 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002479 return false;
2480 }
2481
2482 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002483 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002484
Toma Tabacu79588102015-04-29 10:19:56 +00002485 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2486 uint16_t Bits15To0 = ImmValue & 0xffff;
2487
Toma Tabacua3d056f2015-05-15 09:42:11 +00002488 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002489 // Traditional behaviour seems to special case this particular value. It's
2490 // not clear why other masks are handled differently.
2491 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002492 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2493 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002494 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002495 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002496 return false;
2497 }
2498
2499 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002500 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002501 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2502 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002503 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002504 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002505 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002506 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002507 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002508 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002509
Daniel Sandersa736b372016-04-29 13:33:12 +00002510 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002511 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002512 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002513 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002514 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002515 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002516 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002517
2518 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2519 if (Is32BitImm) {
2520 Error(IDLoc, "instruction requires a 32-bit immediate");
2521 return true;
2522 }
2523
2524 // Traditionally, these immediates are shifted as little as possible and as
2525 // such we align the most significant bit to bit 15 of our temporary.
2526 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2527 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2528 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2529 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002530 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2531 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002532
2533 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002534 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002535
2536 return false;
2537 }
2538
2539 warnIfNoMacro(IDLoc);
2540
2541 // The remaining case is packed with a sequence of dsll and ori with zeros
2542 // being omitted and any neighbouring dsll's being coalesced.
2543 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2544
2545 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2546 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002547 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002548 return false;
2549
2550 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2551 // skip it and defer the shift to the next chunk.
2552 unsigned ShiftCarriedForwards = 16;
2553 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2554 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2555
2556 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002557 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2558 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002559 ShiftCarriedForwards = 0;
2560 }
2561
2562 ShiftCarriedForwards += 16;
2563 }
2564 ShiftCarriedForwards -= 16;
2565
2566 // Finish any remaining shifts left by trailing zeros.
2567 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002568 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002569
2570 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002571 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002572
Matheus Almeida3813d572014-06-19 14:39:14 +00002573 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002574}
Jack Carter92995f12012-10-06 00:53:28 +00002575
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002576bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002577 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002578 const MCOperand &ImmOp = Inst.getOperand(1);
2579 assert(ImmOp.isImm() && "expected immediate operand kind");
2580 const MCOperand &DstRegOp = Inst.getOperand(0);
2581 assert(DstRegOp.isReg() && "expected register operand kind");
2582
2583 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002584 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002585 return true;
2586
2587 return false;
2588}
2589
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002590bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2591 const MCOperand &Offset,
2592 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002593 MCStreamer &Out,
2594 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002595 // la can't produce a usable address when addresses are 64-bit.
2596 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2597 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2598 // We currently can't do this because we depend on the equality
2599 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2600 Error(IDLoc, "la used to load 64-bit address");
2601 // Continue as if we had 'dla' instead.
2602 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002603 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002604 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002605
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002606 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002607 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002608 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002609 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002610 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002611
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002612 if (!Offset.isImm())
2613 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002614 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002615
Scott Egerton24557012016-01-21 15:11:01 +00002616 if (!ABI.ArePtrs64bit()) {
2617 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2618 Is32BitAddress = true;
2619 }
2620
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002621 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002622 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002623}
2624
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002625bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2626 unsigned DstReg, unsigned SrcReg,
2627 bool Is32BitSym, SMLoc IDLoc,
2628 MCStreamer &Out,
2629 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002630 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002631 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002632 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002633
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002634 if (inPicMode() && ABI.IsO32()) {
2635 MCValue Res;
2636 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2637 Error(IDLoc, "expected relocatable expression");
2638 return true;
2639 }
2640 if (Res.getSymB() != nullptr) {
2641 Error(IDLoc, "expected relocatable expression with only one symbol");
2642 return true;
2643 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002644
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002645 // The case where the result register is $25 is somewhat special. If the
2646 // symbol in the final relocation is external and not modified with a
2647 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2648 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2649 Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
2650 !Res.getSymA()->getSymbol().isTemporary()) {
2651 const MCExpr *CallExpr =
2652 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2653 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2654 MCOperand::createExpr(CallExpr), IDLoc, STI);
2655 return false;
2656 }
2657
2658 // The remaining cases are:
2659 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2660 // >addiu $tmp, $tmp, %lo(offset)
2661 // >addiu $rd, $tmp, $rs
2662 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2663 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2664 // >addiu $rd, $tmp, $rs
2665 // The addiu's marked with a '>' may be omitted if they are redundant. If
2666 // this happens then the last instruction must use $rd as the result
2667 // register.
2668 const MipsMCExpr *GotExpr =
2669 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2670 const MCExpr *LoExpr = nullptr;
2671 if (Res.getSymA()->getSymbol().isInSection() ||
2672 Res.getSymA()->getSymbol().isTemporary())
2673 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2674 else if (Res.getConstant() != 0) {
2675 // External symbols fully resolve the symbol with just the %got(symbol)
2676 // but we must still account for any offset to the symbol for expressions
2677 // like symbol+8.
2678 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2679 }
2680
2681 unsigned TmpReg = DstReg;
2682 if (UseSrcReg &&
2683 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2684 SrcReg)) {
2685 // If $rs is the same as $rd, we need to use AT.
2686 // If it is not available we exit.
2687 unsigned ATReg = getATReg(IDLoc);
2688 if (!ATReg)
2689 return true;
2690 TmpReg = ATReg;
2691 }
2692
2693 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2694 MCOperand::createExpr(GotExpr), IDLoc, STI);
2695
2696 if (LoExpr)
2697 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2698 IDLoc, STI);
2699
2700 if (UseSrcReg)
2701 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2702
2703 return false;
2704 }
2705
2706 const MipsMCExpr *HiExpr =
2707 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2708 const MipsMCExpr *LoExpr =
2709 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002710
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002711 // This is the 64-bit symbol address expansion.
2712 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00002713 // We need AT for the 64-bit expansion in the cases where the optional
2714 // source register is the destination register and for the superscalar
2715 // scheduled form.
2716 //
2717 // If it is not available we exit if the destination is the same as the
2718 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002719
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002720 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002721 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002722 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002723 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002724
Simon Dardis3aa8a902017-02-06 12:43:46 +00002725 bool RdRegIsRsReg =
2726 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
2727
2728 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
2729 unsigned ATReg = getATReg(IDLoc);
2730
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002731 // If $rs is the same as $rd:
2732 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2733 // daddiu $at, $at, %higher(sym)
2734 // dsll $at, $at, 16
2735 // daddiu $at, $at, %hi(sym)
2736 // dsll $at, $at, 16
2737 // daddiu $at, $at, %lo(sym)
2738 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002739 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2740 STI);
2741 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2742 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2743 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2744 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2745 IDLoc, STI);
2746 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2747 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2748 IDLoc, STI);
2749 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002750
2751 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00002752 } else if (canUseATReg() && !RdRegIsRsReg) {
2753 unsigned ATReg = getATReg(IDLoc);
2754
2755 // If the $rs is different from $rd or if $rs isn't specified and we
2756 // have $at available:
2757 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2758 // lui $at, %hi(sym)
2759 // daddiu $rd, $rd, %higher(sym)
2760 // daddiu $at, $at, %lo(sym)
2761 // dsll32 $rd, $rd, 0
2762 // daddu $rd, $rd, $at
2763 // (daddu $rd, $rd, $rs)
2764 //
2765 // Which is preferred for superscalar issue.
2766 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2767 STI);
2768 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2769 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2770 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2771 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2772 IDLoc, STI);
2773 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2774 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
2775 if (UseSrcReg)
2776 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
2777
2778 return false;
2779 } else if (!canUseATReg() && !RdRegIsRsReg) {
2780 // Otherwise, synthesize the address in the destination register
2781 // serially:
2782 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2783 // daddiu $rd, $rd, %higher(sym)
2784 // dsll $rd, $rd, 16
2785 // daddiu $rd, $rd, %hi(sym)
2786 // dsll $rd, $rd, 16
2787 // daddiu $rd, $rd, %lo(sym)
2788 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2789 STI);
2790 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2791 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2792 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
2793 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2794 MCOperand::createExpr(HiExpr), IDLoc, STI);
2795 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
2796 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2797 MCOperand::createExpr(LoExpr), IDLoc, STI);
2798 if (UseSrcReg)
2799 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
2800
2801 return false;
2802 } else {
2803 // We have a case where SrcReg == DstReg and we don't have $at
2804 // available. We can't expand this case, so error out appropriately.
2805 assert(SrcReg == DstReg && !canUseATReg() &&
2806 "Could have expanded dla but didn't?");
2807 reportParseError(IDLoc,
2808 "pseudo-instruction requires $at, which is not available");
2809 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002810 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002811 }
2812
2813 // And now, the 32-bit symbol address expansion:
2814 // If $rs is the same as $rd:
2815 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2816 // ori $at, $at, %lo(sym)
2817 // addu $rd, $at, $rd
2818 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2819 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2820 // ori $rd, $rd, %lo(sym)
2821 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002822 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002823 if (UseSrcReg &&
2824 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002825 // If $rs is the same as $rd, we need to use AT.
2826 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002827 unsigned ATReg = getATReg(IDLoc);
2828 if (!ATReg)
2829 return true;
2830 TmpReg = ATReg;
2831 }
2832
Daniel Sandersa736b372016-04-29 13:33:12 +00002833 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2834 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2835 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002836
Toma Tabacufb9d1252015-06-22 12:08:39 +00002837 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002838 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002839 else
Scott Egerton24557012016-01-21 15:11:01 +00002840 assert(
2841 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002842
Toma Tabacu674825c2015-06-16 12:16:24 +00002843 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002844}
2845
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002846bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2847 MCStreamer &Out,
2848 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002849 MipsTargetStreamer &TOut = getTargetStreamer();
2850
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002851 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2852 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002853
2854 MCOperand Offset = Inst.getOperand(0);
2855 if (Offset.isExpr()) {
2856 Inst.clear();
2857 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002858 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2859 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2860 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002861 } else {
2862 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002863 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002864 // If offset fits into 11 bits then this instruction becomes microMIPS
2865 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002866 if (inMicroMipsMode())
2867 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002868 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002869 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00002870 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002871 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00002872 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002873 Inst.clear();
2874 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002875 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2876 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2877 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002878 }
2879 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002880 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002881
Zoran Jovanovicada70912015-09-07 11:56:37 +00002882 // If .set reorder is active and branch instruction has a delay slot,
2883 // emit a NOP after it.
2884 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2885 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002886 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002887
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002888 return false;
2889}
2890
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002891bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2892 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002893 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002894 const MCOperand &DstRegOp = Inst.getOperand(0);
2895 assert(DstRegOp.isReg() && "expected register operand kind");
2896
2897 const MCOperand &ImmOp = Inst.getOperand(1);
2898 assert(ImmOp.isImm() && "expected immediate operand kind");
2899
2900 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002901 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2902 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002903
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002904 bool IsLikely = false;
2905
Toma Tabacue1e460d2015-06-11 10:36:10 +00002906 unsigned OpCode = 0;
2907 switch(Inst.getOpcode()) {
2908 case Mips::BneImm:
2909 OpCode = Mips::BNE;
2910 break;
2911 case Mips::BeqImm:
2912 OpCode = Mips::BEQ;
2913 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002914 case Mips::BEQLImmMacro:
2915 OpCode = Mips::BEQL;
2916 IsLikely = true;
2917 break;
2918 case Mips::BNELImmMacro:
2919 OpCode = Mips::BNEL;
2920 IsLikely = true;
2921 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002922 default:
2923 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2924 break;
2925 }
2926
2927 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002928 if (ImmValue == 0) {
2929 if (IsLikely) {
2930 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
2931 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
2932 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
2933 } else
2934 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2935 STI);
2936 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002937 warnIfNoMacro(IDLoc);
2938
2939 unsigned ATReg = getATReg(IDLoc);
2940 if (!ATReg)
2941 return true;
2942
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002943 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002944 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002945 return true;
2946
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002947 if (IsLikely) {
2948 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
2949 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
2950 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
2951 } else
2952 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002953 }
2954 return false;
2955}
2956
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002957void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002958 const MCSubtargetInfo *STI, bool IsLoad,
2959 bool IsImmOpnd) {
2960 if (IsLoad) {
2961 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2962 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002963 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002964 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2965}
2966
2967void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2968 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2969 MipsTargetStreamer &TOut = getTargetStreamer();
2970
2971 unsigned DstReg = Inst.getOperand(0).getReg();
2972 unsigned BaseReg = Inst.getOperand(1).getReg();
2973
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002974 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002975 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2976 unsigned DstRegClassID =
2977 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2978 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2979 (DstRegClassID == Mips::GPR64RegClassID);
2980
2981 if (IsImmOpnd) {
2982 // Try to use DstReg as the temporary.
2983 if (IsGPR && (BaseReg != DstReg)) {
2984 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2985 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2986 STI);
2987 return;
2988 }
2989
Matheus Almeida7de68e72014-06-18 14:46:05 +00002990 // At this point we need AT to perform the expansions and we exit if it is
2991 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002992 unsigned ATReg = getATReg(IDLoc);
2993 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002994 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002995
2996 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2997 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2998 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002999 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00003000
Daniel Sandersfba875f2016-04-29 13:43:45 +00003001 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003002 MCOperand LoOperand = MCOperand::createExpr(
3003 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3004 MCOperand HiOperand = MCOperand::createExpr(
3005 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003006
3007 // Try to use DstReg as the temporary.
3008 if (IsGPR && (BaseReg != DstReg)) {
3009 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3010 LoOperand, DstReg, IDLoc, STI);
3011 return;
3012 }
3013
3014 // At this point we need AT to perform the expansions and we exit if it is
3015 // not available.
3016 unsigned ATReg = getATReg(IDLoc);
3017 if (!ATReg)
3018 return;
3019
3020 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3021 LoOperand, ATReg, IDLoc, STI);
3022}
3023
3024void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3025 const MCSubtargetInfo *STI,
3026 bool IsImmOpnd) {
3027 MipsTargetStreamer &TOut = getTargetStreamer();
3028
3029 unsigned SrcReg = Inst.getOperand(0).getReg();
3030 unsigned BaseReg = Inst.getOperand(1).getReg();
3031
Daniel Sanders241c6792016-05-12 14:01:50 +00003032 if (IsImmOpnd) {
3033 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
3034 Inst.getOperand(2).getImm(),
3035 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3036 return;
3037 }
3038
Daniel Sandersfba875f2016-04-29 13:43:45 +00003039 unsigned ATReg = getATReg(IDLoc);
3040 if (!ATReg)
3041 return;
3042
Daniel Sandersfba875f2016-04-29 13:43:45 +00003043 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003044 MCOperand LoOperand = MCOperand::createExpr(
3045 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3046 MCOperand HiOperand = MCOperand::createExpr(
3047 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003048 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3049 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003050}
3051
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003052bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3053 MCStreamer &Out,
3054 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003055 unsigned OpNum = Inst.getNumOperands();
3056 unsigned Opcode = Inst.getOpcode();
3057 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3058
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003059 assert(Inst.getOperand(OpNum - 1).isImm() &&
3060 Inst.getOperand(OpNum - 2).isReg() &&
3061 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003062
3063 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3064 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003065 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3066 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3067 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3068 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003069 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003070 if (inMicroMipsMode() && hasMips32r6())
3071 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3072 else
3073 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3074 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003075
3076 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003077 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003078 return false;
3079}
3080
Toma Tabacu1a108322015-06-17 13:20:24 +00003081bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003082 MCStreamer &Out,
3083 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003084 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003085 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003086 unsigned PseudoOpcode = Inst.getOpcode();
3087 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003088 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003089 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3090
3091 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003092 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003093
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003094 unsigned TrgReg;
3095 if (TrgOp.isReg())
3096 TrgReg = TrgOp.getReg();
3097 else if (TrgOp.isImm()) {
3098 warnIfNoMacro(IDLoc);
3099 EmittedNoMacroWarning = true;
3100
3101 TrgReg = getATReg(IDLoc);
3102 if (!TrgReg)
3103 return true;
3104
3105 switch(PseudoOpcode) {
3106 default:
3107 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3108 case Mips::BLTImmMacro:
3109 PseudoOpcode = Mips::BLT;
3110 break;
3111 case Mips::BLEImmMacro:
3112 PseudoOpcode = Mips::BLE;
3113 break;
3114 case Mips::BGEImmMacro:
3115 PseudoOpcode = Mips::BGE;
3116 break;
3117 case Mips::BGTImmMacro:
3118 PseudoOpcode = Mips::BGT;
3119 break;
3120 case Mips::BLTUImmMacro:
3121 PseudoOpcode = Mips::BLTU;
3122 break;
3123 case Mips::BLEUImmMacro:
3124 PseudoOpcode = Mips::BLEU;
3125 break;
3126 case Mips::BGEUImmMacro:
3127 PseudoOpcode = Mips::BGEU;
3128 break;
3129 case Mips::BGTUImmMacro:
3130 PseudoOpcode = Mips::BGTU;
3131 break;
3132 case Mips::BLTLImmMacro:
3133 PseudoOpcode = Mips::BLTL;
3134 break;
3135 case Mips::BLELImmMacro:
3136 PseudoOpcode = Mips::BLEL;
3137 break;
3138 case Mips::BGELImmMacro:
3139 PseudoOpcode = Mips::BGEL;
3140 break;
3141 case Mips::BGTLImmMacro:
3142 PseudoOpcode = Mips::BGTL;
3143 break;
3144 case Mips::BLTULImmMacro:
3145 PseudoOpcode = Mips::BLTUL;
3146 break;
3147 case Mips::BLEULImmMacro:
3148 PseudoOpcode = Mips::BLEUL;
3149 break;
3150 case Mips::BGEULImmMacro:
3151 PseudoOpcode = Mips::BGEUL;
3152 break;
3153 case Mips::BGTULImmMacro:
3154 PseudoOpcode = Mips::BGTUL;
3155 break;
3156 }
3157
3158 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003159 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003160 return true;
3161 }
3162
Toma Tabacu1a108322015-06-17 13:20:24 +00003163 switch (PseudoOpcode) {
3164 case Mips::BLT:
3165 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003166 case Mips::BLTL:
3167 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003168 AcceptsEquality = false;
3169 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003170 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3171 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003172 ZeroSrcOpcode = Mips::BGTZ;
3173 ZeroTrgOpcode = Mips::BLTZ;
3174 break;
3175 case Mips::BLE:
3176 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003177 case Mips::BLEL:
3178 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003179 AcceptsEquality = true;
3180 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003181 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3182 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003183 ZeroSrcOpcode = Mips::BGEZ;
3184 ZeroTrgOpcode = Mips::BLEZ;
3185 break;
3186 case Mips::BGE:
3187 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003188 case Mips::BGEL:
3189 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003190 AcceptsEquality = true;
3191 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003192 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3193 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003194 ZeroSrcOpcode = Mips::BLEZ;
3195 ZeroTrgOpcode = Mips::BGEZ;
3196 break;
3197 case Mips::BGT:
3198 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003199 case Mips::BGTL:
3200 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003201 AcceptsEquality = false;
3202 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003203 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3204 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003205 ZeroSrcOpcode = Mips::BLTZ;
3206 ZeroTrgOpcode = Mips::BGTZ;
3207 break;
3208 default:
3209 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3210 }
3211
Toma Tabacu1a108322015-06-17 13:20:24 +00003212 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3213 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3214 if (IsSrcRegZero && IsTrgRegZero) {
3215 // FIXME: All of these Opcode-specific if's are needed for compatibility
3216 // with GAS' behaviour. However, they may not generate the most efficient
3217 // code in some circumstances.
3218 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003219 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3220 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003221 return false;
3222 }
3223 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003224 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3225 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003226 Warning(IDLoc, "branch is always taken");
3227 return false;
3228 }
3229 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003230 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3231 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003232 Warning(IDLoc, "branch is always taken");
3233 return false;
3234 }
3235 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003236 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3237 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003238 return false;
3239 }
3240 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003241 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3242 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003243 return false;
3244 }
3245 if (AcceptsEquality) {
3246 // If both registers are $0 and the pseudo-branch accepts equality, it
3247 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003248 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3249 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003250 Warning(IDLoc, "branch is always taken");
3251 return false;
3252 }
3253 // If both registers are $0 and the pseudo-branch does not accept
3254 // equality, it will never be taken, so we don't have to emit anything.
3255 return false;
3256 }
3257 if (IsSrcRegZero || IsTrgRegZero) {
3258 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3259 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3260 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3261 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3262 // the pseudo-branch will never be taken, so we don't emit anything.
3263 // This only applies to unsigned pseudo-branches.
3264 return false;
3265 }
3266 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3267 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3268 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3269 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3270 // the pseudo-branch will always be taken, so we emit an unconditional
3271 // branch.
3272 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003273 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3274 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003275 Warning(IDLoc, "branch is always taken");
3276 return false;
3277 }
3278 if (IsUnsigned) {
3279 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3280 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3281 // the pseudo-branch will be taken only when the non-zero register is
3282 // different from 0, so we emit a BNEZ.
3283 //
3284 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3285 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3286 // the pseudo-branch will be taken only when the non-zero register is
3287 // equal to 0, so we emit a BEQZ.
3288 //
3289 // Because only BLEU and BGEU branch on equality, we can use the
3290 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003291 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3292 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3293 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003294 return false;
3295 }
3296 // If we have a signed pseudo-branch and one of the registers is $0,
3297 // we can use an appropriate compare-to-zero branch. We select which one
3298 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003299 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3300 IsSrcRegZero ? TrgReg : SrcReg,
3301 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003302 return false;
3303 }
3304
3305 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3306 // expansions. If it is not available, we return.
3307 unsigned ATRegNum = getATReg(IDLoc);
3308 if (!ATRegNum)
3309 return true;
3310
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003311 if (!EmittedNoMacroWarning)
3312 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003313
3314 // SLT fits well with 2 of our 4 pseudo-branches:
3315 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3316 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3317 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3318 // This is accomplished by using a BNEZ with the result of the SLT.
3319 //
3320 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3321 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3322 // Because only BGE and BLE branch on equality, we can use the
3323 // AcceptsEquality variable to decide when to emit the BEQZ.
3324 // Note that the order of the SLT arguments doesn't change between
3325 // opposites.
3326 //
3327 // The same applies to the unsigned variants, except that SLTu is used
3328 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003329 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3330 ReverseOrderSLT ? TrgReg : SrcReg,
3331 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003332
Daniel Sandersa736b372016-04-29 13:33:12 +00003333 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3334 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3335 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3336 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003337 return false;
3338}
3339
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003340bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3341 const MCSubtargetInfo *STI, const bool IsMips64,
3342 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003343 MipsTargetStreamer &TOut = getTargetStreamer();
3344
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003345 warnIfNoMacro(IDLoc);
3346
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003347 const MCOperand &RdRegOp = Inst.getOperand(0);
3348 assert(RdRegOp.isReg() && "expected register operand kind");
3349 unsigned RdReg = RdRegOp.getReg();
3350
3351 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003352 assert(RsRegOp.isReg() && "expected register operand kind");
3353 unsigned RsReg = RsRegOp.getReg();
3354
Simon Dardis12850ee2017-01-31 10:49:24 +00003355 unsigned RtReg;
3356 int64_t ImmValue;
3357
3358 const MCOperand &RtOp = Inst.getOperand(2);
3359 assert((RtOp.isReg() || RtOp.isImm()) &&
3360 "expected register or immediate operand kind");
3361 if (RtOp.isReg())
3362 RtReg = RtOp.getReg();
3363 else
3364 ImmValue = RtOp.getImm();
3365
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003366 unsigned DivOp;
3367 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003368 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003369
3370 if (IsMips64) {
3371 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3372 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003373 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003374 } else {
3375 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3376 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003377 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003378 }
3379
3380 bool UseTraps = useTraps();
3381
Simon Dardis12850ee2017-01-31 10:49:24 +00003382 if (RtOp.isImm()) {
3383 unsigned ATReg = getATReg(IDLoc);
3384 if (!ATReg)
3385 return true;
3386
3387 if (ImmValue == 0) {
3388 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64)
3389 Warning(IDLoc, "dividing zero by zero");
3390 else
3391 Warning(IDLoc, "division by zero");
3392 if (UseTraps)
3393 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3394 else
3395 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3396 return false;
3397 }
3398
3399 if (ImmValue == 1) {
3400 TOut.emitRRR(Mips::ADDu, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
3401 return false;
3402 } else if (Signed && ImmValue == -1) {
3403 TOut.emitRRR(SubOp, RdReg, Mips::ZERO, RsReg, IDLoc, STI);
3404 return false;
3405 } else {
3406 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
3407 false, Inst.getLoc(), Out, STI))
3408 return true;
3409 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
3410 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
3411 return false;
3412 }
3413 return true;
3414 }
3415
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003416 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
3417 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
3418 Warning(IDLoc, "dividing zero by zero");
3419 if (IsMips64) {
3420 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
3421 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003422 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003423 return false;
3424 }
3425
Daniel Sandersa736b372016-04-29 13:33:12 +00003426 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003427 return false;
3428 }
3429 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00003430 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003431 return false;
3432 }
3433 }
3434
3435 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3436 Warning(IDLoc, "division by zero");
3437 if (Signed) {
3438 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003439 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003440 return false;
3441 }
3442
Daniel Sandersa736b372016-04-29 13:33:12 +00003443 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003444 return false;
3445 }
3446 }
3447
3448 // FIXME: The values for these two BranchTarget variables may be different in
3449 // micromips. These magic numbers need to be removed.
3450 unsigned BranchTargetNoTraps;
3451 unsigned BranchTarget;
3452
3453 if (UseTraps) {
3454 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003455 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003456 } else {
3457 BranchTarget = IsMips64 ? 20 : 16;
3458 BranchTargetNoTraps = 8;
3459 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003460 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003461 }
3462
Daniel Sandersa736b372016-04-29 13:33:12 +00003463 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003464
3465 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003466 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003467
3468 if (!Signed) {
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003469 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003470 return false;
3471 }
3472
3473 unsigned ATReg = getATReg(IDLoc);
3474 if (!ATReg)
3475 return true;
3476
Daniel Sandersa736b372016-04-29 13:33:12 +00003477 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003478 if (IsMips64) {
3479 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003480 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3481 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3482 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003483 } else {
3484 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003485 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3486 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003487 }
3488
3489 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003490 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003491 else {
3492 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003493 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3494 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3495 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003496 }
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003497 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003498 return false;
3499}
3500
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003501bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003502 SMLoc IDLoc, MCStreamer &Out,
3503 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003504 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003505
3506 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3507 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3508 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3509
3510 unsigned FirstReg = Inst.getOperand(0).getReg();
3511 unsigned SecondReg = Inst.getOperand(1).getReg();
3512 unsigned ThirdReg = Inst.getOperand(2).getReg();
3513
3514 if (hasMips1() && !hasMips2()) {
3515 unsigned ATReg = getATReg(IDLoc);
3516 if (!ATReg)
3517 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003518 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3519 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3520 TOut.emitNop(IDLoc, STI);
3521 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3522 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3523 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3524 TOut.emitNop(IDLoc, STI);
3525 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3526 : Mips::CVT_W_S,
3527 FirstReg, SecondReg, IDLoc, STI);
3528 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3529 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003530 return false;
3531 }
3532
Daniel Sandersa736b372016-04-29 13:33:12 +00003533 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3534 : Mips::TRUNC_W_S,
3535 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003536
3537 return false;
3538}
3539
Daniel Sanders6394ee52015-10-15 14:52:58 +00003540bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003541 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003542 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003543 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003544 }
3545
Toma Tabacud88d79c2015-06-23 14:39:42 +00003546 const MCOperand &DstRegOp = Inst.getOperand(0);
3547 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003548 const MCOperand &SrcRegOp = Inst.getOperand(1);
3549 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003550 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3551 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3552
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003553 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00003554 unsigned DstReg = DstRegOp.getReg();
3555 unsigned SrcReg = SrcRegOp.getReg();
3556 int64_t OffsetValue = OffsetImmOp.getImm();
3557
3558 // NOTE: We always need AT for ULHU, as it is always used as the source
3559 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003560 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003561 unsigned ATReg = getATReg(IDLoc);
3562 if (!ATReg)
3563 return true;
3564
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003565 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
3566 if (IsLargeOffset) {
3567 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
3568 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003569 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00003570 }
3571
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003572 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
3573 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
3574 if (isLittle())
3575 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003576
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003577 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
3578 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00003579
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003580 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
3581 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00003582
Daniel Sandersa736b372016-04-29 13:33:12 +00003583 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003584 FirstOffset, IDLoc, STI);
3585 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00003586 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00003587 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003588
3589 return false;
3590}
3591
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003592bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003593 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003594 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003595 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003596 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003597
3598 const MCOperand &DstRegOp = Inst.getOperand(0);
3599 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003600 const MCOperand &SrcRegOp = Inst.getOperand(1);
3601 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003602 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3603 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3604
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003605 MipsTargetStreamer &TOut = getTargetStreamer();
3606 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003607 unsigned SrcReg = SrcRegOp.getReg();
3608 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003609
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003610 warnIfNoMacro(IDLoc);
3611 unsigned ATReg = getATReg(IDLoc);
3612 if (!ATReg)
3613 return true;
3614
3615 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
3616 if (IsLargeOffset) {
3617 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
3618 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003619 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003620 }
3621
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003622 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
3623 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
3624 if (isLittle())
3625 std::swap(FirstOffset, SecondOffset);
3626
3627 if (IsLargeOffset) {
3628 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
3629 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
3630 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
3631 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
3632 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
3633 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003634 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003635 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
3636 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
3637 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003638 }
3639
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003640 return false;
3641}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003642
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003643bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3644 const MCSubtargetInfo *STI) {
3645 if (hasMips32r6() || hasMips64r6()) {
3646 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3647 }
3648
3649 const MCOperand &DstRegOp = Inst.getOperand(0);
3650 assert(DstRegOp.isReg() && "expected register operand kind");
3651 const MCOperand &SrcRegOp = Inst.getOperand(1);
3652 assert(SrcRegOp.isReg() && "expected register operand kind");
3653 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3654 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3655
3656 MipsTargetStreamer &TOut = getTargetStreamer();
3657 unsigned DstReg = DstRegOp.getReg();
3658 unsigned SrcReg = SrcRegOp.getReg();
3659 int64_t OffsetValue = OffsetImmOp.getImm();
3660
3661 // Compute left/right load/store offsets.
3662 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
3663 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
3664 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
3665 if (isLittle())
3666 std::swap(LxlOffset, LxrOffset);
3667
3668 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
3669 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
3670 unsigned TmpReg = SrcReg;
3671 if (IsLargeOffset || DoMove) {
3672 warnIfNoMacro(IDLoc);
3673 TmpReg = getATReg(IDLoc);
3674 if (!TmpReg)
3675 return true;
3676 }
3677
3678 if (IsLargeOffset) {
3679 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
3680 IDLoc, Out, STI))
3681 return true;
3682 }
3683
3684 if (DoMove)
3685 std::swap(DstReg, TmpReg);
3686
3687 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
3688 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
3689 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
3690 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
3691
3692 if (DoMove)
3693 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003694
3695 return false;
3696}
3697
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003698bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003699 MCStreamer &Out,
3700 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003701 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003702
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003703 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3704 assert(Inst.getOperand(0).isReg() &&
3705 Inst.getOperand(1).isReg() &&
3706 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003707
3708 unsigned ATReg = Mips::NoRegister;
3709 unsigned FinalDstReg = Mips::NoRegister;
3710 unsigned DstReg = Inst.getOperand(0).getReg();
3711 unsigned SrcReg = Inst.getOperand(1).getReg();
3712 int64_t ImmValue = Inst.getOperand(2).getImm();
3713
3714 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3715
3716 unsigned FinalOpcode = Inst.getOpcode();
3717
3718 if (DstReg == SrcReg) {
3719 ATReg = getATReg(Inst.getLoc());
3720 if (!ATReg)
3721 return true;
3722 FinalDstReg = DstReg;
3723 DstReg = ATReg;
3724 }
3725
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003726 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003727 switch (FinalOpcode) {
3728 default:
3729 llvm_unreachable("unimplemented expansion");
3730 case (Mips::ADDi):
3731 FinalOpcode = Mips::ADD;
3732 break;
3733 case (Mips::ADDiu):
3734 FinalOpcode = Mips::ADDu;
3735 break;
3736 case (Mips::ANDi):
3737 FinalOpcode = Mips::AND;
3738 break;
3739 case (Mips::NORImm):
3740 FinalOpcode = Mips::NOR;
3741 break;
3742 case (Mips::ORi):
3743 FinalOpcode = Mips::OR;
3744 break;
3745 case (Mips::SLTi):
3746 FinalOpcode = Mips::SLT;
3747 break;
3748 case (Mips::SLTiu):
3749 FinalOpcode = Mips::SLTu;
3750 break;
3751 case (Mips::XORi):
3752 FinalOpcode = Mips::XOR;
3753 break;
3754 }
3755
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003756 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003757 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003758 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003759 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003760 return false;
3761 }
3762 return true;
3763}
3764
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003765bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3766 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003767 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003768 unsigned ATReg = Mips::NoRegister;
3769 unsigned DReg = Inst.getOperand(0).getReg();
3770 unsigned SReg = Inst.getOperand(1).getReg();
3771 unsigned TReg = Inst.getOperand(2).getReg();
3772 unsigned TmpReg = DReg;
3773
3774 unsigned FirstShift = Mips::NOP;
3775 unsigned SecondShift = Mips::NOP;
3776
3777 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003778 if (DReg == SReg) {
3779 TmpReg = getATReg(Inst.getLoc());
3780 if (!TmpReg)
3781 return true;
3782 }
3783
3784 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003785 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3786 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003787 return false;
3788 }
3789
3790 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003791 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003792 return false;
3793 }
3794
3795 return true;
3796 }
3797
3798 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003799 switch (Inst.getOpcode()) {
3800 default:
3801 llvm_unreachable("unexpected instruction opcode");
3802 case Mips::ROL:
3803 FirstShift = Mips::SRLV;
3804 SecondShift = Mips::SLLV;
3805 break;
3806 case Mips::ROR:
3807 FirstShift = Mips::SLLV;
3808 SecondShift = Mips::SRLV;
3809 break;
3810 }
3811
3812 ATReg = getATReg(Inst.getLoc());
3813 if (!ATReg)
3814 return true;
3815
Daniel Sandersa736b372016-04-29 13:33:12 +00003816 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3817 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3818 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3819 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003820
3821 return false;
3822 }
3823
3824 return true;
3825}
3826
3827bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003828 MCStreamer &Out,
3829 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003830 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003831 unsigned ATReg = Mips::NoRegister;
3832 unsigned DReg = Inst.getOperand(0).getReg();
3833 unsigned SReg = Inst.getOperand(1).getReg();
3834 int64_t ImmValue = Inst.getOperand(2).getImm();
3835
3836 unsigned FirstShift = Mips::NOP;
3837 unsigned SecondShift = Mips::NOP;
3838
3839 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003840 if (Inst.getOpcode() == Mips::ROLImm) {
3841 uint64_t MaxShift = 32;
3842 uint64_t ShiftValue = ImmValue;
3843 if (ImmValue != 0)
3844 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003845 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003846 return false;
3847 }
3848
3849 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003850 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003851 return false;
3852 }
3853
3854 return true;
3855 }
3856
3857 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003858 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003859 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003860 return false;
3861 }
3862
3863 switch (Inst.getOpcode()) {
3864 default:
3865 llvm_unreachable("unexpected instruction opcode");
3866 case Mips::ROLImm:
3867 FirstShift = Mips::SLL;
3868 SecondShift = Mips::SRL;
3869 break;
3870 case Mips::RORImm:
3871 FirstShift = Mips::SRL;
3872 SecondShift = Mips::SLL;
3873 break;
3874 }
3875
3876 ATReg = getATReg(Inst.getLoc());
3877 if (!ATReg)
3878 return true;
3879
Daniel Sandersa736b372016-04-29 13:33:12 +00003880 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3881 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3882 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003883
3884 return false;
3885 }
3886
3887 return true;
3888}
3889
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003890bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3891 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003892 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003893 unsigned ATReg = Mips::NoRegister;
3894 unsigned DReg = Inst.getOperand(0).getReg();
3895 unsigned SReg = Inst.getOperand(1).getReg();
3896 unsigned TReg = Inst.getOperand(2).getReg();
3897 unsigned TmpReg = DReg;
3898
3899 unsigned FirstShift = Mips::NOP;
3900 unsigned SecondShift = Mips::NOP;
3901
3902 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003903 if (TmpReg == SReg) {
3904 TmpReg = getATReg(Inst.getLoc());
3905 if (!TmpReg)
3906 return true;
3907 }
3908
3909 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003910 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3911 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003912 return false;
3913 }
3914
3915 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003916 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003917 return false;
3918 }
3919
3920 return true;
3921 }
3922
3923 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003924 switch (Inst.getOpcode()) {
3925 default:
3926 llvm_unreachable("unexpected instruction opcode");
3927 case Mips::DROL:
3928 FirstShift = Mips::DSRLV;
3929 SecondShift = Mips::DSLLV;
3930 break;
3931 case Mips::DROR:
3932 FirstShift = Mips::DSLLV;
3933 SecondShift = Mips::DSRLV;
3934 break;
3935 }
3936
3937 ATReg = getATReg(Inst.getLoc());
3938 if (!ATReg)
3939 return true;
3940
Daniel Sandersa736b372016-04-29 13:33:12 +00003941 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3942 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3943 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3944 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003945
3946 return false;
3947 }
3948
3949 return true;
3950}
3951
3952bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003953 MCStreamer &Out,
3954 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003955 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003956 unsigned ATReg = Mips::NoRegister;
3957 unsigned DReg = Inst.getOperand(0).getReg();
3958 unsigned SReg = Inst.getOperand(1).getReg();
3959 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3960
3961 unsigned FirstShift = Mips::NOP;
3962 unsigned SecondShift = Mips::NOP;
3963
3964 MCInst TmpInst;
3965
3966 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003967 unsigned FinalOpcode = Mips::NOP;
3968 if (ImmValue == 0)
3969 FinalOpcode = Mips::DROTR;
3970 else if (ImmValue % 32 == 0)
3971 FinalOpcode = Mips::DROTR32;
3972 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3973 if (Inst.getOpcode() == Mips::DROLImm)
3974 FinalOpcode = Mips::DROTR32;
3975 else
3976 FinalOpcode = Mips::DROTR;
3977 } else if (ImmValue >= 33) {
3978 if (Inst.getOpcode() == Mips::DROLImm)
3979 FinalOpcode = Mips::DROTR;
3980 else
3981 FinalOpcode = Mips::DROTR32;
3982 }
3983
3984 uint64_t ShiftValue = ImmValue % 32;
3985 if (Inst.getOpcode() == Mips::DROLImm)
3986 ShiftValue = (32 - ImmValue % 32) % 32;
3987
Daniel Sandersa736b372016-04-29 13:33:12 +00003988 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003989
3990 return false;
3991 }
3992
3993 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003994 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003995 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003996 return false;
3997 }
3998
3999 switch (Inst.getOpcode()) {
4000 default:
4001 llvm_unreachable("unexpected instruction opcode");
4002 case Mips::DROLImm:
4003 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4004 FirstShift = Mips::DSLL;
4005 SecondShift = Mips::DSRL32;
4006 }
4007 if (ImmValue == 32) {
4008 FirstShift = Mips::DSLL32;
4009 SecondShift = Mips::DSRL32;
4010 }
4011 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4012 FirstShift = Mips::DSLL32;
4013 SecondShift = Mips::DSRL;
4014 }
4015 break;
4016 case Mips::DRORImm:
4017 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4018 FirstShift = Mips::DSRL;
4019 SecondShift = Mips::DSLL32;
4020 }
4021 if (ImmValue == 32) {
4022 FirstShift = Mips::DSRL32;
4023 SecondShift = Mips::DSLL32;
4024 }
4025 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4026 FirstShift = Mips::DSRL32;
4027 SecondShift = Mips::DSLL;
4028 }
4029 break;
4030 }
4031
4032 ATReg = getATReg(Inst.getLoc());
4033 if (!ATReg)
4034 return true;
4035
Daniel Sandersa736b372016-04-29 13:33:12 +00004036 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4037 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4038 Inst.getLoc(), STI);
4039 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004040
4041 return false;
4042 }
4043
4044 return true;
4045}
4046
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004047bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4048 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004049 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004050 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4051 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4052
Daniel Sandersa736b372016-04-29 13:33:12 +00004053 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004054 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004055 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004056 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004057 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4058 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004059
4060 return false;
4061}
4062
Simon Dardisaff4d142016-10-18 14:28:00 +00004063static unsigned nextReg(unsigned Reg) {
4064 switch (Reg) {
4065 case Mips::ZERO: return Mips::AT;
4066 case Mips::AT: return Mips::V0;
4067 case Mips::V0: return Mips::V1;
4068 case Mips::V1: return Mips::A0;
4069 case Mips::A0: return Mips::A1;
4070 case Mips::A1: return Mips::A2;
4071 case Mips::A2: return Mips::A3;
4072 case Mips::A3: return Mips::T0;
4073 case Mips::T0: return Mips::T1;
4074 case Mips::T1: return Mips::T2;
4075 case Mips::T2: return Mips::T3;
4076 case Mips::T3: return Mips::T4;
4077 case Mips::T4: return Mips::T5;
4078 case Mips::T5: return Mips::T6;
4079 case Mips::T6: return Mips::T7;
4080 case Mips::T7: return Mips::S0;
4081 case Mips::S0: return Mips::S1;
4082 case Mips::S1: return Mips::S2;
4083 case Mips::S2: return Mips::S3;
4084 case Mips::S3: return Mips::S4;
4085 case Mips::S4: return Mips::S5;
4086 case Mips::S5: return Mips::S6;
4087 case Mips::S6: return Mips::S7;
4088 case Mips::S7: return Mips::T8;
4089 case Mips::T8: return Mips::T9;
4090 case Mips::T9: return Mips::K0;
4091 case Mips::K0: return Mips::K1;
4092 case Mips::K1: return Mips::GP;
4093 case Mips::GP: return Mips::SP;
4094 case Mips::SP: return Mips::FP;
4095 case Mips::FP: return Mips::RA;
4096 case Mips::RA: return Mips::ZERO;
4097 default: return 0;
4098 }
4099
4100}
4101
4102// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4103// lw $<reg+1>>, offset+4($reg2)'
4104// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4105// sw $<reg+1>>, offset+4($reg2)'
4106// for O32.
4107bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4108 MCStreamer &Out,
4109 const MCSubtargetInfo *STI,
4110 bool IsLoad) {
4111 if (!isABI_O32())
4112 return true;
4113
4114 warnIfNoMacro(IDLoc);
4115
4116 MipsTargetStreamer &TOut = getTargetStreamer();
4117 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4118 unsigned FirstReg = Inst.getOperand(0).getReg();
4119 unsigned SecondReg = nextReg(FirstReg);
4120 unsigned BaseReg = Inst.getOperand(1).getReg();
4121 if (!SecondReg)
4122 return true;
4123
4124 warnIfRegIndexIsAT(FirstReg, IDLoc);
4125
4126 assert(Inst.getOperand(2).isImm() &&
4127 "Offset for load macro is not immediate!");
4128
4129 MCOperand &FirstOffset = Inst.getOperand(2);
4130 signed NextOffset = FirstOffset.getImm() + 4;
4131 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4132
4133 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4134 return true;
4135
4136 // For loads, clobber the base register with the second load instead of the
4137 // first if the BaseReg == FirstReg.
4138 if (FirstReg != BaseReg || !IsLoad) {
4139 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4140 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4141 } else {
4142 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4143 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4144 }
4145
4146 return false;
4147}
4148
Simon Dardis43115a12016-11-21 20:30:41 +00004149bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4150 const MCSubtargetInfo *STI) {
4151
4152 warnIfNoMacro(IDLoc);
4153 MipsTargetStreamer &TOut = getTargetStreamer();
4154
4155 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4156 Inst.getOperand(2).getReg() != Mips::ZERO) {
4157 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4158 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4159 IDLoc, STI);
4160 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4161 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4162 return false;
4163 }
4164
4165 unsigned Reg = 0;
4166 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4167 Reg = Inst.getOperand(2).getReg();
4168 } else {
4169 Reg = Inst.getOperand(1).getReg();
4170 }
4171 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4172 return false;
4173}
4174
4175bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4176 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004177 warnIfNoMacro(IDLoc);
4178 MipsTargetStreamer &TOut = getTargetStreamer();
4179
4180 unsigned Opc;
4181 int64_t Imm = Inst.getOperand(2).getImm();
4182 unsigned Reg = Inst.getOperand(1).getReg();
4183
4184 if (Imm == 0) {
4185 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4186 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4187 return false;
4188 } else {
4189
4190 if (Reg == Mips::ZERO) {
4191 Warning(IDLoc, "comparison is always false");
4192 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4193 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4194 return false;
4195 }
4196
4197 if (Imm > -0x8000 && Imm < 0) {
4198 Imm = -Imm;
4199 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4200 } else {
4201 Opc = Mips::XORi;
4202 }
4203 }
4204 if (!isUInt<16>(Imm)) {
4205 unsigned ATReg = getATReg(IDLoc);
4206 if (!ATReg)
4207 return true;
4208
4209 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4210 Out, STI))
4211 return true;
4212
4213 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4214 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4215 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4216 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4217 return false;
4218 }
4219
4220 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4221 Imm, IDLoc, STI);
4222 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4223 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4224 return false;
4225}
4226
Daniel Sandersc5537422016-07-27 13:49:44 +00004227unsigned
4228MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
4229 const OperandVector &Operands) {
4230 switch (Inst.getOpcode()) {
4231 default:
4232 return Match_Success;
4233 case Mips::DATI:
4234 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00004235 case Mips::DATI_MM64R6:
4236 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00004237 if (static_cast<MipsOperand &>(*Operands[1])
4238 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
4239 return Match_Success;
4240 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00004241 }
4242}
Simon Dardis730fdb72017-01-16 13:55:58 +00004243
Matheus Almeida595fcab2014-06-11 15:05:56 +00004244unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00004245 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00004246 // As described by the MIPSR6 spec, daui must not use the zero operand for
4247 // its source operand.
4248 case Mips::DAUI:
4249 case Mips::DAUI_MM64R6:
4250 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4251 Inst.getOperand(1).getReg() == Mips::ZERO_64)
4252 return Match_RequiresNoZeroRegister;
4253 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00004254 // As described by the Mips32r2 spec, the registers Rd and Rs for
4255 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00004256 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00004257 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00004258 case Mips::JALR_HB:
4259 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00004260 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00004261 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4262 return Match_RequiresDifferentSrcAndDst;
4263 return Match_Success;
4264 case Mips::LWP_MM:
4265 case Mips::LWP_MMR6:
4266 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
4267 return Match_RequiresDifferentSrcAndDst;
4268 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00004269 case Mips::SYNC:
4270 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
4271 return Match_NonZeroOperandForSync;
4272 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004273 // As described the MIPSR6 spec, the compact branches that compare registers
4274 // must:
4275 // a) Not use the zero register.
4276 // b) Not use the same register twice.
4277 // c) rs < rt for bnec, beqc.
4278 // NB: For this case, the encoding will swap the operands as their
4279 // ordering doesn't matter. GAS performs this transformation too.
4280 // Hence, that constraint does not have to be enforced.
4281 //
4282 // The compact branches that branch iff the signed addition of two registers
4283 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
4284 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004285 case Mips::BLEZC: case Mips::BLEZC_MMR6:
4286 case Mips::BGEZC: case Mips::BGEZC_MMR6:
4287 case Mips::BGTZC: case Mips::BGTZC_MMR6:
4288 case Mips::BLTZC: case Mips::BLTZC_MMR6:
4289 case Mips::BEQZC: case Mips::BEQZC_MMR6:
4290 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004291 case Mips::BLEZC64:
4292 case Mips::BGEZC64:
4293 case Mips::BGTZC64:
4294 case Mips::BLTZC64:
4295 case Mips::BEQZC64:
4296 case Mips::BNEZC64:
4297 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4298 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004299 return Match_RequiresNoZeroRegister;
4300 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004301 case Mips::BGEC: case Mips::BGEC_MMR6:
4302 case Mips::BLTC: case Mips::BLTC_MMR6:
4303 case Mips::BGEUC: case Mips::BGEUC_MMR6:
4304 case Mips::BLTUC: case Mips::BLTUC_MMR6:
4305 case Mips::BEQC: case Mips::BEQC_MMR6:
4306 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004307 case Mips::BGEC64:
4308 case Mips::BLTC64:
4309 case Mips::BGEUC64:
4310 case Mips::BLTUC64:
4311 case Mips::BEQC64:
4312 case Mips::BNEC64:
4313 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4314 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004315 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00004316 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4317 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004318 return Match_RequiresNoZeroRegister;
4319 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4320 return Match_RequiresDifferentOperands;
4321 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004322 }
Simon Dardis730fdb72017-01-16 13:55:58 +00004323
4324 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
4325 if ((TSFlags & MipsII::HasFCCRegOperand) &&
4326 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
4327 return Match_NoFCCRegisterForCurrentISA;
4328
4329 return Match_Success;
4330
Matheus Almeida595fcab2014-06-11 15:05:56 +00004331}
4332
Daniel Sanders52da7af2015-11-06 12:11:03 +00004333static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
4334 uint64_t ErrorInfo) {
4335 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
4336 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
4337 if (ErrorLoc == SMLoc())
4338 return Loc;
4339 return ErrorLoc;
4340 }
4341 return Loc;
4342}
4343
David Blaikie960ea3f2014-06-08 16:18:35 +00004344bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4345 OperandVector &Operands,
4346 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004347 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00004348 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004349 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00004350 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004351 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00004352
4353 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004354 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004355 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00004356 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004357 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00004358 case Match_MissingFeature:
4359 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4360 return true;
4361 case Match_InvalidOperand: {
4362 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00004363 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004364 if (ErrorInfo >= Operands.size())
4365 return Error(IDLoc, "too few operands for instruction");
4366
Daniel Sanders52da7af2015-11-06 12:11:03 +00004367 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00004368 if (ErrorLoc == SMLoc())
4369 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00004370 }
4371
4372 return Error(ErrorLoc, "invalid operand for instruction");
4373 }
Simon Dardisc4463c92016-10-18 14:42:13 +00004374 case Match_NonZeroOperandForSync:
4375 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00004376 case Match_MnemonicFail:
4377 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00004378 case Match_RequiresDifferentSrcAndDst:
4379 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00004380 case Match_RequiresDifferentOperands:
4381 return Error(IDLoc, "registers must be different");
4382 case Match_RequiresNoZeroRegister:
4383 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00004384 case Match_RequiresSameSrcAndDst:
4385 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00004386 case Match_NoFCCRegisterForCurrentISA:
4387 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4388 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00004389 case Match_Immz:
4390 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004391 case Match_UImm1_0:
4392 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4393 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00004394 case Match_UImm2_0:
4395 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4396 "expected 2-bit unsigned immediate");
4397 case Match_UImm2_1:
4398 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4399 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00004400 case Match_UImm3_0:
4401 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4402 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004403 case Match_UImm4_0:
4404 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4405 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00004406 case Match_SImm4_0:
4407 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4408 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004409 case Match_UImm5_0:
4410 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4411 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00004412 case Match_SImm5_0:
4413 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4414 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004415 case Match_UImm5_1:
4416 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4417 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004418 case Match_UImm5_32:
4419 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4420 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004421 case Match_UImm5_33:
4422 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4423 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004424 case Match_UImm5_0_Report_UImm6:
4425 // This is used on UImm5 operands that have a corresponding UImm5_32
4426 // operand to avoid confusing the user.
4427 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4428 "expected 6-bit unsigned immediate");
4429 case Match_UImm5_Lsl2:
4430 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4431 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00004432 case Match_UImmRange2_64:
4433 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4434 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00004435 case Match_UImm6_0:
4436 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4437 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00004438 case Match_UImm6_Lsl2:
4439 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4440 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00004441 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00004442 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4443 "expected 6-bit signed immediate");
4444 case Match_UImm7_0:
4445 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4446 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00004447 case Match_UImm7_N1:
4448 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4449 "expected immediate in range -1 .. 126");
4450 case Match_SImm7_Lsl2:
4451 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4452 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00004453 case Match_UImm8_0:
4454 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4455 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00004456 case Match_UImm10_0:
4457 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4458 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00004459 case Match_SImm10_0:
4460 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4461 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00004462 case Match_SImm11_0:
4463 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4464 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00004465 case Match_UImm16:
4466 case Match_UImm16_Relaxed:
4467 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4468 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004469 case Match_SImm16:
4470 case Match_SImm16_Relaxed:
4471 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4472 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00004473 case Match_SImm19_Lsl2:
4474 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4475 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00004476 case Match_UImm20_0:
4477 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4478 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00004479 case Match_UImm26_0:
4480 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4481 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00004482 case Match_SImm32:
4483 case Match_SImm32_Relaxed:
4484 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4485 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00004486 case Match_UImm32_Coerced:
4487 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4488 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00004489 case Match_MemSImm9:
4490 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4491 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00004492 case Match_MemSImm10:
4493 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4494 "expected memory with 10-bit signed offset");
4495 case Match_MemSImm10Lsl1:
4496 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4497 "expected memory with 11-bit signed offset and multiple of 2");
4498 case Match_MemSImm10Lsl2:
4499 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4500 "expected memory with 12-bit signed offset and multiple of 4");
4501 case Match_MemSImm10Lsl3:
4502 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4503 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00004504 case Match_MemSImm11:
4505 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4506 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00004507 case Match_MemSImm12:
4508 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4509 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004510 case Match_MemSImm16:
4511 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4512 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00004513 }
Craig Topper589ceee2015-01-03 08:16:34 +00004514
4515 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00004516}
4517
Toma Tabacud9d344b2015-04-27 14:05:04 +00004518void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
4519 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
4520 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
4521 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004522}
4523
Toma Tabacu81496c12015-05-20 08:54:45 +00004524void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
4525 if (!AssemblerOptions.back()->isMacro())
4526 Warning(Loc, "macro instruction expanded into multiple instructions");
4527}
4528
Daniel Sandersef638fe2014-10-03 15:37:37 +00004529void
4530MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
4531 SMRange Range, bool ShowColors) {
4532 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00004533 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00004534 ShowColors);
4535}
4536
Jack Carter1ac53222013-02-20 23:11:17 +00004537int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004538 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004539
Vladimir Medic4c299852013-11-06 11:27:05 +00004540 CC = StringSwitch<unsigned>(Name)
4541 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004542 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00004543 .Case("a0", 4)
4544 .Case("a1", 5)
4545 .Case("a2", 6)
4546 .Case("a3", 7)
4547 .Case("v0", 2)
4548 .Case("v1", 3)
4549 .Case("s0", 16)
4550 .Case("s1", 17)
4551 .Case("s2", 18)
4552 .Case("s3", 19)
4553 .Case("s4", 20)
4554 .Case("s5", 21)
4555 .Case("s6", 22)
4556 .Case("s7", 23)
4557 .Case("k0", 26)
4558 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004559 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00004560 .Case("sp", 29)
4561 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004562 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00004563 .Case("ra", 31)
4564 .Case("t0", 8)
4565 .Case("t1", 9)
4566 .Case("t2", 10)
4567 .Case("t3", 11)
4568 .Case("t4", 12)
4569 .Case("t5", 13)
4570 .Case("t6", 14)
4571 .Case("t7", 15)
4572 .Case("t8", 24)
4573 .Case("t9", 25)
4574 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004575
Toma Tabacufda445c2014-09-15 15:33:01 +00004576 if (!(isABI_N32() || isABI_N64()))
4577 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004578
Daniel Sandersef638fe2014-10-03 15:37:37 +00004579 if (12 <= CC && CC <= 15) {
4580 // Name is one of t4-t7
4581 AsmToken RegTok = getLexer().peekTok();
4582 SMRange RegRange = RegTok.getLocRange();
4583
4584 StringRef FixedName = StringSwitch<StringRef>(Name)
4585 .Case("t4", "t0")
4586 .Case("t5", "t1")
4587 .Case("t6", "t2")
4588 .Case("t7", "t3")
4589 .Default("");
4590 assert(FixedName != "" && "Register name is not one of t4-t7.");
4591
4592 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
4593 "Did you mean $" + FixedName + "?", RegRange);
4594 }
4595
Toma Tabacufda445c2014-09-15 15:33:01 +00004596 // Although SGI documentation just cuts out t0-t3 for n32/n64,
4597 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
4598 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
4599 if (8 <= CC && CC <= 11)
4600 CC += 4;
4601
4602 if (CC == -1)
4603 CC = StringSwitch<unsigned>(Name)
4604 .Case("a4", 8)
4605 .Case("a5", 9)
4606 .Case("a6", 10)
4607 .Case("a7", 11)
4608 .Case("kt0", 26)
4609 .Case("kt1", 27)
4610 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004611
4612 return CC;
4613}
Jack Carterd0bd6422013-04-18 00:41:53 +00004614
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004615int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
4616 int CC;
4617
4618 CC = StringSwitch<unsigned>(Name)
4619 .Case("hwr_cpunum", 0)
4620 .Case("hwr_synci_step", 1)
4621 .Case("hwr_cc", 2)
4622 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00004623 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004624 .Default(-1);
4625
4626 return CC;
4627}
4628
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004629int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00004630 if (Name[0] == 'f') {
4631 StringRef NumString = Name.substr(1);
4632 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004633 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004634 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004635 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00004636 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004637 return IntVal;
4638 }
4639 return -1;
4640}
Jack Cartera63b16a2012-09-07 00:23:42 +00004641
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004642int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004643 if (Name.startswith("fcc")) {
4644 StringRef NumString = Name.substr(3);
4645 unsigned IntVal;
4646 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004647 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004648 if (IntVal > 7) // There are only 8 fcc registers.
4649 return -1;
4650 return IntVal;
4651 }
4652 return -1;
4653}
4654
4655int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00004656 if (Name.startswith("ac")) {
4657 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004658 unsigned IntVal;
4659 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004660 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004661 if (IntVal > 3) // There are only 3 acc registers.
4662 return -1;
4663 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00004664 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004665 return -1;
4666}
Jack Carterd0bd6422013-04-18 00:41:53 +00004667
Jack Carter5dc8ac92013-09-25 23:50:44 +00004668int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
4669 unsigned IntVal;
4670
4671 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
4672 return -1;
4673
4674 if (IntVal > 31)
4675 return -1;
4676
4677 return IntVal;
4678}
4679
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004680int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
4681 int CC;
4682
4683 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00004684 .Case("msair", 0)
4685 .Case("msacsr", 1)
4686 .Case("msaaccess", 2)
4687 .Case("msasave", 3)
4688 .Case("msamodify", 4)
4689 .Case("msarequest", 5)
4690 .Case("msamap", 6)
4691 .Case("msaunmap", 7)
4692 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004693
4694 return CC;
4695}
4696
Simon Dardis3aa8a902017-02-06 12:43:46 +00004697bool MipsAsmParser::canUseATReg() {
4698 return AssemblerOptions.back()->getATRegIndex() != 0;
4699}
4700
Toma Tabacu89a712b2015-04-15 10:48:56 +00004701unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004702 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004703 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004704 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004705 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004706 return 0;
4707 }
4708 unsigned AT = getReg(
4709 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004710 return AT;
4711}
Jack Carter0b744b32012-10-04 02:29:46 +00004712
Jack Carterd0bd6422013-04-18 00:41:53 +00004713unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004714 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004715}
4716
Toma Tabacu13964452014-09-04 13:23:44 +00004717bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004718 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004719 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004720
Jack Carter30a59822012-10-04 04:03:53 +00004721 // Check if the current operand has a custom associated parser, if so, try to
4722 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004723 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4724 if (ResTy == MatchOperand_Success)
4725 return false;
4726 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4727 // there was a match, but an error occurred, in which case, just return that
4728 // the operand parsing failed.
4729 if (ResTy == MatchOperand_ParseFail)
4730 return true;
4731
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004732 DEBUG(dbgs() << ".. Generic Parser\n");
4733
Jack Carterb4dbc172012-09-05 23:34:03 +00004734 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004735 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004736 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004737 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004738
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004739 // Almost all registers have been parsed by custom parsers. There is only
4740 // one exception to this. $zero (and it's alias $0) will reach this point
4741 // for div, divu, and similar instructions because it is not an operand
4742 // to the instruction definition but an explicit register. Special case
4743 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004744 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004745 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004746
Jack Carterd0bd6422013-04-18 00:41:53 +00004747 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004748 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004749 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004750 return true;
4751
Jack Carter873c7242013-01-12 01:03:14 +00004752 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004753 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004754 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004755 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004756 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004757
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004758 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004759 return false;
4760 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004761 default: {
4762 DEBUG(dbgs() << ".. generic integer expression\n");
4763
4764 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00004765 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004766 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004767 return true;
4768
Jack Carter873c7242013-01-12 01:03:14 +00004769 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4770
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004771 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004772 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004773 }
Jack Carter0b744b32012-10-04 02:29:46 +00004774 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004775 return true;
4776}
4777
Jack Carterb5cf5902013-04-17 00:18:04 +00004778bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004779 switch (Expr->getKind()) {
4780 case MCExpr::Constant:
4781 return true;
4782 case MCExpr::SymbolRef:
4783 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4784 case MCExpr::Binary:
4785 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4786 if (!isEvaluated(BE->getLHS()))
4787 return false;
4788 return isEvaluated(BE->getRHS());
4789 }
4790 case MCExpr::Unary:
4791 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004792 case MCExpr::Target:
4793 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004794 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004795 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004796}
Jack Carterd0bd6422013-04-18 00:41:53 +00004797
Jack Carterb4dbc172012-09-05 23:34:03 +00004798bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4799 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004800 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004801 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004802 if (ResTy == MatchOperand_Success) {
4803 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004804 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004805 StartLoc = Operand.getStartLoc();
4806 EndLoc = Operand.getEndLoc();
4807
4808 // AFAIK, we only support numeric registers and named GPR's in CFI
4809 // directives.
4810 // Don't worry about eating tokens before failing. Using an unrecognised
4811 // register is a parse error.
4812 if (Operand.isGPRAsmReg()) {
4813 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004814 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004815 }
4816
4817 return (RegNo == (unsigned)-1);
4818 }
4819
4820 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004821 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004822}
4823
Jack Carterb5cf5902013-04-17 00:18:04 +00004824bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00004825 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004826
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004827 if (isParenExpr)
4828 return getParser().parseParenExprOfDepth(0, Res, S);
4829 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004830}
4831
Alex Bradbury58eba092016-11-01 16:32:05 +00004832OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004833MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004834 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004835 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004836 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004837 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004838 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00004839 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004840 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004841 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004842
Jack Carterb5cf5902013-04-17 00:18:04 +00004843 if (getLexer().getKind() == AsmToken::LParen) {
4844 Parser.Lex();
4845 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004846 }
4847
Jack Carterb5cf5902013-04-17 00:18:04 +00004848 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004849 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004850 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004851
Jack Carterd0bd6422013-04-18 00:41:53 +00004852 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004853 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004854 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004855 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004856 SMLoc E =
4857 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004858 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004859 return MatchOperand_Success;
4860 }
4861 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004862 SMLoc E =
4863 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004864
Jack Carterd0bd6422013-04-18 00:41:53 +00004865 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004866 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00004867 auto Base = MipsOperand::createGPRReg(
4868 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00004869 Operands.push_back(
4870 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004871 return MatchOperand_Success;
4872 }
Simon Dardis858915f2016-10-18 15:17:17 +00004873 MCBinaryExpr::Opcode Opcode;
4874 // GAS and LLVM treat comparison operators different. GAS will generate -1
4875 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
4876 // highly unlikely to be found in a memory offset expression, we don't
4877 // handle them.
4878 switch (Tok.getKind()) {
4879 case AsmToken::Plus:
4880 Opcode = MCBinaryExpr::Add;
4881 Parser.Lex();
4882 break;
4883 case AsmToken::Minus:
4884 Opcode = MCBinaryExpr::Sub;
4885 Parser.Lex();
4886 break;
4887 case AsmToken::Star:
4888 Opcode = MCBinaryExpr::Mul;
4889 Parser.Lex();
4890 break;
4891 case AsmToken::Pipe:
4892 Opcode = MCBinaryExpr::Or;
4893 Parser.Lex();
4894 break;
4895 case AsmToken::Amp:
4896 Opcode = MCBinaryExpr::And;
4897 Parser.Lex();
4898 break;
4899 case AsmToken::LessLess:
4900 Opcode = MCBinaryExpr::Shl;
4901 Parser.Lex();
4902 break;
4903 case AsmToken::GreaterGreater:
4904 Opcode = MCBinaryExpr::LShr;
4905 Parser.Lex();
4906 break;
4907 case AsmToken::Caret:
4908 Opcode = MCBinaryExpr::Xor;
4909 Parser.Lex();
4910 break;
4911 case AsmToken::Slash:
4912 Opcode = MCBinaryExpr::Div;
4913 Parser.Lex();
4914 break;
4915 case AsmToken::Percent:
4916 Opcode = MCBinaryExpr::Mod;
4917 Parser.Lex();
4918 break;
4919 default:
4920 Error(Parser.getTok().getLoc(), "'(' or expression expected");
4921 return MatchOperand_ParseFail;
4922 }
4923 const MCExpr * NextExpr;
4924 if (getParser().parseExpression(NextExpr))
4925 return MatchOperand_ParseFail;
4926 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004927 }
4928
Jack Carterd0bd6422013-04-18 00:41:53 +00004929 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004930 }
4931
Toma Tabacu13964452014-09-04 13:23:44 +00004932 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004933 if (Res != MatchOperand_Success)
4934 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004935
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004936 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004937 Error(Parser.getTok().getLoc(), "')' expected");
4938 return MatchOperand_ParseFail;
4939 }
4940
Jack Carter873c7242013-01-12 01:03:14 +00004941 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4942
Jack Carterd0bd6422013-04-18 00:41:53 +00004943 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004944
Craig Topper062a2ba2014-04-25 05:30:21 +00004945 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004946 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004947
Jack Carterd0bd6422013-04-18 00:41:53 +00004948 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004949 std::unique_ptr<MipsOperand> op(
4950 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004951 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004952 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004953 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004954 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004955 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4956 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004957 if (IdVal->evaluateAsAbsolute(Imm))
4958 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004959 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004960 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004961 getContext());
4962 }
4963
David Blaikie960ea3f2014-06-08 16:18:35 +00004964 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004965 return MatchOperand_Success;
4966}
4967
David Blaikie960ea3f2014-06-08 16:18:35 +00004968bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004969 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004970 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004971 if (Sym) {
4972 SMLoc S = Parser.getTok().getLoc();
4973 const MCExpr *Expr;
4974 if (Sym->isVariable())
4975 Expr = Sym->getVariableValue();
4976 else
4977 return false;
4978 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004979 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004980 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004981 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004982 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004983 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004984 if (ResTy == MatchOperand_Success) {
4985 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004986 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004987 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004988 llvm_unreachable("Should never ParseFail");
4989 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004990 }
Jack Carterd76b2372013-03-21 21:44:16 +00004991 }
4992 }
4993 return false;
4994}
Jack Carterd0bd6422013-04-18 00:41:53 +00004995
Alex Bradbury58eba092016-11-01 16:32:05 +00004996OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004997MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004998 StringRef Identifier,
4999 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005000 int Index = matchCPURegisterName(Identifier);
5001 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005002 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005003 Index, Identifier, getContext().getRegisterInfo(), S,
5004 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005005 return MatchOperand_Success;
5006 }
5007
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005008 Index = matchHWRegsRegisterName(Identifier);
5009 if (Index != -1) {
5010 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005011 Index, Identifier, getContext().getRegisterInfo(), S,
5012 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005013 return MatchOperand_Success;
5014 }
5015
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005016 Index = matchFPURegisterName(Identifier);
5017 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005018 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005019 Index, Identifier, getContext().getRegisterInfo(), S,
5020 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005021 return MatchOperand_Success;
5022 }
5023
5024 Index = matchFCCRegisterName(Identifier);
5025 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005026 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005027 Index, Identifier, getContext().getRegisterInfo(), S,
5028 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005029 return MatchOperand_Success;
5030 }
5031
5032 Index = matchACRegisterName(Identifier);
5033 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005034 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005035 Index, Identifier, getContext().getRegisterInfo(), S,
5036 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005037 return MatchOperand_Success;
5038 }
5039
5040 Index = matchMSA128RegisterName(Identifier);
5041 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005042 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005043 Index, Identifier, getContext().getRegisterInfo(), S,
5044 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005045 return MatchOperand_Success;
5046 }
5047
5048 Index = matchMSA128CtrlRegisterName(Identifier);
5049 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005050 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005051 Index, Identifier, getContext().getRegisterInfo(), S,
5052 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005053 return MatchOperand_Success;
5054 }
5055
5056 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00005057}
5058
Alex Bradbury58eba092016-11-01 16:32:05 +00005059OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005060MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005061 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00005062 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005063
5064 if (Token.is(AsmToken::Identifier)) {
5065 DEBUG(dbgs() << ".. identifier\n");
5066 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00005067 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005068 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00005069 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005070 } else if (Token.is(AsmToken::Integer)) {
5071 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00005072 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005073 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
5074 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005075 return MatchOperand_Success;
5076 }
5077
5078 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
5079
5080 return MatchOperand_NoMatch;
5081}
5082
Alex Bradbury58eba092016-11-01 16:32:05 +00005083OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005084MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005085 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005086 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005087
5088 auto Token = Parser.getTok();
5089
5090 SMLoc S = Token.getLoc();
5091
5092 if (Token.isNot(AsmToken::Dollar)) {
5093 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
5094 if (Token.is(AsmToken::Identifier)) {
5095 if (searchSymbolAlias(Operands))
5096 return MatchOperand_Success;
5097 }
5098 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
5099 return MatchOperand_NoMatch;
5100 }
5101 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005102
Toma Tabacu13964452014-09-04 13:23:44 +00005103 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00005104 if (ResTy == MatchOperand_Success) {
5105 Parser.Lex(); // $
5106 Parser.Lex(); // identifier
5107 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005108 return ResTy;
5109}
5110
Alex Bradbury58eba092016-11-01 16:32:05 +00005111OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005112MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005113 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005114 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005115
5116 SMLoc S = getLexer().getLoc();
5117
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005118 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005119 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005120 if (ResTy != MatchOperand_NoMatch)
5121 return ResTy;
5122
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005123 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00005124 const MCExpr *Expr = nullptr;
5125 if (Parser.parseExpression(Expr)) {
5126 // We have no way of knowing if a symbol was consumed so we must ParseFail
5127 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005128 }
Daniel Sandersffd84362014-04-01 10:41:48 +00005129 Operands.push_back(
5130 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005131 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00005132}
5133
Alex Bradbury58eba092016-11-01 16:32:05 +00005134OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005135MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005136 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00005137 const MCExpr *IdVal;
5138 // If the first token is '$' we may have register operand.
5139 if (Parser.getTok().is(AsmToken::Dollar))
5140 return MatchOperand_NoMatch;
5141 SMLoc S = Parser.getTok().getLoc();
5142 if (getParser().parseExpression(IdVal))
5143 return MatchOperand_ParseFail;
5144 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00005145 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00005146 int64_t Val = MCE->getValue();
5147 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5148 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00005149 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00005150 return MatchOperand_Success;
5151}
5152
Alex Bradbury58eba092016-11-01 16:32:05 +00005153OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005154MipsAsmParser::parseRegisterList(OperandVector &Operands) {
5155 MCAsmParser &Parser = getParser();
5156 SmallVector<unsigned, 10> Regs;
5157 unsigned RegNo;
5158 unsigned PrevReg = Mips::NoRegister;
5159 bool RegRange = false;
5160 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5161
5162 if (Parser.getTok().isNot(AsmToken::Dollar))
5163 return MatchOperand_ParseFail;
5164
5165 SMLoc S = Parser.getTok().getLoc();
5166 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
5167 SMLoc E = getLexer().getLoc();
5168 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
5169 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
5170 if (RegRange) {
5171 // Remove last register operand because registers from register range
5172 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005173 if ((isGP64bit() && RegNo == Mips::RA_64) ||
5174 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005175 Regs.push_back(RegNo);
5176 } else {
5177 unsigned TmpReg = PrevReg + 1;
5178 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005179 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
5180 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
5181 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005182 Error(E, "invalid register operand");
5183 return MatchOperand_ParseFail;
5184 }
5185
5186 PrevReg = TmpReg;
5187 Regs.push_back(TmpReg++);
5188 }
5189 }
5190
5191 RegRange = false;
5192 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005193 if ((PrevReg == Mips::NoRegister) &&
5194 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
5195 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005196 Error(E, "$16 or $31 expected");
5197 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005198 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
5199 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
5200 !isGP64bit()) ||
5201 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
5202 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
5203 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005204 Error(E, "invalid register operand");
5205 return MatchOperand_ParseFail;
5206 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005207 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
5208 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
5209 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005210 Error(E, "consecutive register numbers expected");
5211 return MatchOperand_ParseFail;
5212 }
5213
5214 Regs.push_back(RegNo);
5215 }
5216
5217 if (Parser.getTok().is(AsmToken::Minus))
5218 RegRange = true;
5219
5220 if (!Parser.getTok().isNot(AsmToken::Minus) &&
5221 !Parser.getTok().isNot(AsmToken::Comma)) {
5222 Error(E, "',' or '-' expected");
5223 return MatchOperand_ParseFail;
5224 }
5225
5226 Lex(); // Consume comma or minus
5227 if (Parser.getTok().isNot(AsmToken::Dollar))
5228 break;
5229
5230 PrevReg = RegNo;
5231 }
5232
5233 SMLoc E = Parser.getTok().getLoc();
5234 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5235 parseMemOperand(Operands);
5236 return MatchOperand_Success;
5237}
5238
Alex Bradbury58eba092016-11-01 16:32:05 +00005239OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005240MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
5241 MCAsmParser &Parser = getParser();
5242
5243 SMLoc S = Parser.getTok().getLoc();
5244 if (parseAnyRegister(Operands) != MatchOperand_Success)
5245 return MatchOperand_ParseFail;
5246
5247 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00005248 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00005249
Benjamin Kramer2b68d152016-05-09 10:31:17 +00005250 Operands.pop_back();
5251 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005252 return MatchOperand_Success;
5253}
5254
Alex Bradbury58eba092016-11-01 16:32:05 +00005255OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00005256MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
5257 MCAsmParser &Parser = getParser();
5258 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5259 SmallVector<unsigned, 10> Regs;
5260
5261 if (Parser.getTok().isNot(AsmToken::Dollar))
5262 return MatchOperand_ParseFail;
5263
5264 SMLoc S = Parser.getTok().getLoc();
5265
5266 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5267 return MatchOperand_ParseFail;
5268
5269 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5270 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5271 Regs.push_back(RegNo);
5272
5273 SMLoc E = Parser.getTok().getLoc();
5274 if (Parser.getTok().isNot(AsmToken::Comma)) {
5275 Error(E, "',' expected");
5276 return MatchOperand_ParseFail;
5277 }
5278
5279 // Remove comma.
5280 Parser.Lex();
5281
5282 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5283 return MatchOperand_ParseFail;
5284
5285 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5286 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5287 Regs.push_back(RegNo);
5288
5289 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5290
5291 return MatchOperand_Success;
5292}
5293
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005294/// Sometimes (i.e. load/stores) the operand may be followed immediately by
5295/// either this.
5296/// ::= '(', register, ')'
5297/// handle it before we iterate so we don't get tripped up by the lack of
5298/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005299bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005300 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005301 if (getLexer().is(AsmToken::LParen)) {
5302 Operands.push_back(
5303 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
5304 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005305 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005306 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005307 return Error(Loc, "unexpected token in argument list");
5308 }
5309 if (Parser.getTok().isNot(AsmToken::RParen)) {
5310 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005311 return Error(Loc, "unexpected token, expected ')'");
5312 }
5313 Operands.push_back(
5314 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
5315 Parser.Lex();
5316 }
5317 return false;
5318}
5319
5320/// Sometimes (i.e. in MSA) the operand may be followed immediately by
5321/// either one of these.
5322/// ::= '[', register, ']'
5323/// ::= '[', integer, ']'
5324/// handle it before we iterate so we don't get tripped up by the lack of
5325/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005326bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00005327 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005328 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005329 if (getLexer().is(AsmToken::LBrac)) {
5330 Operands.push_back(
5331 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
5332 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005333 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005334 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005335 return Error(Loc, "unexpected token in argument list");
5336 }
5337 if (Parser.getTok().isNot(AsmToken::RBrac)) {
5338 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005339 return Error(Loc, "unexpected token, expected ']'");
5340 }
5341 Operands.push_back(
5342 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
5343 Parser.Lex();
5344 }
5345 return false;
5346}
5347
David Blaikie960ea3f2014-06-08 16:18:35 +00005348bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
5349 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005350 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005351 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005352
5353 // We have reached first instruction, module directive are now forbidden.
5354 getTargetStreamer().forbidModuleDirective();
5355
Vladimir Medic74593e62013-07-17 15:00:42 +00005356 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00005357 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005358 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00005359 }
Vladimir Medic64828a12013-07-16 10:07:14 +00005360 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005361 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005362
5363 // Read the remaining operands.
5364 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5365 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005366 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005367 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005368 return Error(Loc, "unexpected token in argument list");
5369 }
Toma Tabacu13964452014-09-04 13:23:44 +00005370 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005371 return true;
5372 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00005373
Jack Carterd0bd6422013-04-18 00:41:53 +00005374 while (getLexer().is(AsmToken::Comma)) {
5375 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00005376 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005377 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005378 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005379 return Error(Loc, "unexpected token in argument list");
5380 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005381 // Parse bracket and parenthesis suffixes before we iterate
5382 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00005383 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005384 return true;
5385 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00005386 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005387 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005388 }
5389 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005390 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5391 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005392 return Error(Loc, "unexpected token in argument list");
5393 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005394 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00005395 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00005396}
5397
Nirav Dave996fc132016-05-05 14:15:46 +00005398// FIXME: Given that these have the same name, these should both be
5399// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005400bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005401 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005402 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00005403}
5404
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005405bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005406 return Error(Loc, ErrorMsg);
5407}
5408
Jack Carter0b744b32012-10-04 02:29:46 +00005409bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005410 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005411 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00005412
5413 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00005414 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00005415
5416 Parser.Lex(); // Eat "noat".
5417
Jack Carterd0bd6422013-04-18 00:41:53 +00005418 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005419 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005420 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005421 return false;
5422 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005423
5424 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005425 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005426 return false;
5427}
Jack Carterd0bd6422013-04-18 00:41:53 +00005428
Jack Carter0b744b32012-10-04 02:29:46 +00005429bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00005430 // Line can be: ".set at", which sets $at to $1
5431 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00005432 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00005433 Parser.Lex(); // Eat "at".
5434
Jack Carter0b744b32012-10-04 02:29:46 +00005435 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005436 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00005437 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00005438
5439 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005440 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005441 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00005442 }
5443
5444 if (getLexer().isNot(AsmToken::Equal)) {
5445 reportParseError("unexpected token, expected equals sign");
5446 return false;
5447 }
5448 Parser.Lex(); // Eat "=".
5449
5450 if (getLexer().isNot(AsmToken::Dollar)) {
5451 if (getLexer().is(AsmToken::EndOfStatement)) {
5452 reportParseError("no register specified");
5453 return false;
5454 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00005455 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00005456 return false;
5457 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005458 }
5459 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00005460
Toma Tabacu16a74492015-02-13 10:30:57 +00005461 // Find out what "reg" is.
5462 unsigned AtRegNo;
5463 const AsmToken &Reg = Parser.getTok();
5464 if (Reg.is(AsmToken::Identifier)) {
5465 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
5466 } else if (Reg.is(AsmToken::Integer)) {
5467 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00005468 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00005469 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00005470 return false;
5471 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005472
5473 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00005474 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005475 reportParseError("invalid register");
5476 return false;
5477 }
5478 Parser.Lex(); // Eat "reg".
5479
5480 // If this is not the end of the statement, report an error.
5481 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5482 reportParseError("unexpected token, expected end of statement");
5483 return false;
5484 }
5485
5486 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
5487
5488 Parser.Lex(); // Consume the EndOfStatement.
5489 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005490}
5491
5492bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005493 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005494 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005495 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005496 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005497 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005498 return false;
5499 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005500 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00005501 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005502 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005503 return false;
5504}
5505
5506bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005507 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005508 Parser.Lex();
5509 // If this is not the end of the statement, report an error.
5510 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005511 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005512 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005513 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005514 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005515 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005516 Parser.Lex(); // Consume the EndOfStatement.
5517 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005518}
5519
5520bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005521 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005522 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005523 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005524 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005525 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005526 return false;
5527 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005528 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005529 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005530 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005531 return false;
5532}
5533
5534bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005535 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005536 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005537 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005538 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005539 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005540 return false;
5541 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005542 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005543 reportParseError("`noreorder' must be set before `nomacro'");
5544 return false;
5545 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005546 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005547 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005548 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005549 return false;
5550}
Jack Carterd76b2372013-03-21 21:44:16 +00005551
Daniel Sanders44934432014-08-07 12:03:36 +00005552bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005553 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005554 Parser.Lex();
5555
5556 // If this is not the end of the statement, report an error.
5557 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005558 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005559
5560 setFeatureBits(Mips::FeatureMSA, "msa");
5561 getTargetStreamer().emitDirectiveSetMsa();
5562 return false;
5563}
5564
5565bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005566 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005567 Parser.Lex();
5568
5569 // If this is not the end of the statement, report an error.
5570 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005571 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005572
5573 clearFeatureBits(Mips::FeatureMSA, "msa");
5574 getTargetStreamer().emitDirectiveSetNoMsa();
5575 return false;
5576}
5577
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005578bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005579 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005580 Parser.Lex(); // Eat "nodsp".
5581
5582 // If this is not the end of the statement, report an error.
5583 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5584 reportParseError("unexpected token, expected end of statement");
5585 return false;
5586 }
5587
5588 clearFeatureBits(Mips::FeatureDSP, "dsp");
5589 getTargetStreamer().emitDirectiveSetNoDsp();
5590 return false;
5591}
5592
Toma Tabacucc2502d2014-11-04 17:18:07 +00005593bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005594 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005595 Parser.Lex(); // Eat "mips16".
5596
Jack Carter39536722014-01-22 23:08:42 +00005597 // If this is not the end of the statement, report an error.
5598 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005599 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005600 return false;
5601 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005602
5603 setFeatureBits(Mips::FeatureMips16, "mips16");
5604 getTargetStreamer().emitDirectiveSetMips16();
5605 Parser.Lex(); // Consume the EndOfStatement.
5606 return false;
5607}
5608
5609bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005610 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005611 Parser.Lex(); // Eat "nomips16".
5612
5613 // If this is not the end of the statement, report an error.
5614 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5615 reportParseError("unexpected token, expected end of statement");
5616 return false;
5617 }
5618
5619 clearFeatureBits(Mips::FeatureMips16, "mips16");
5620 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005621 Parser.Lex(); // Consume the EndOfStatement.
5622 return false;
5623}
5624
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005625bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005626 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005627 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005628 // Line can be: .set fp=32
5629 // .set fp=xx
5630 // .set fp=64
5631 Parser.Lex(); // Eat fp token
5632 AsmToken Tok = Parser.getTok();
5633 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005634 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005635 return false;
5636 }
5637 Parser.Lex(); // Eat '=' token.
5638 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005639
5640 if (!parseFpABIValue(FpAbiVal, ".set"))
5641 return false;
5642
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005643 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005644 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005645 return false;
5646 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005647 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005648 Parser.Lex(); // Consume the EndOfStatement.
5649 return false;
5650}
5651
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005652bool MipsAsmParser::parseSetOddSPRegDirective() {
5653 MCAsmParser &Parser = getParser();
5654
5655 Parser.Lex(); // Eat "oddspreg".
5656 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5657 reportParseError("unexpected token, expected end of statement");
5658 return false;
5659 }
5660
5661 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5662 getTargetStreamer().emitDirectiveSetOddSPReg();
5663 return false;
5664}
5665
5666bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5667 MCAsmParser &Parser = getParser();
5668
5669 Parser.Lex(); // Eat "nooddspreg".
5670 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5671 reportParseError("unexpected token, expected end of statement");
5672 return false;
5673 }
5674
5675 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5676 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5677 return false;
5678}
5679
Toma Tabacu9db22db2014-09-09 10:15:38 +00005680bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005681 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005682 SMLoc Loc = getLexer().getLoc();
5683
5684 Parser.Lex();
5685 if (getLexer().isNot(AsmToken::EndOfStatement))
5686 return reportParseError("unexpected token, expected end of statement");
5687
5688 // Always keep an element on the options "stack" to prevent the user
5689 // from changing the initial options. This is how we remember them.
5690 if (AssemblerOptions.size() == 2)
5691 return reportParseError(Loc, ".set pop with no .set push");
5692
Akira Hatanakab11ef082015-11-14 06:35:56 +00005693 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005694 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005695 setAvailableFeatures(
5696 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5697 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005698
5699 getTargetStreamer().emitDirectiveSetPop();
5700 return false;
5701}
5702
5703bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005704 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005705 Parser.Lex();
5706 if (getLexer().isNot(AsmToken::EndOfStatement))
5707 return reportParseError("unexpected token, expected end of statement");
5708
5709 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005710 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005711 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005712
5713 getTargetStreamer().emitDirectiveSetPush();
5714 return false;
5715}
5716
Toma Tabacu29696502015-06-02 09:48:04 +00005717bool MipsAsmParser::parseSetSoftFloatDirective() {
5718 MCAsmParser &Parser = getParser();
5719 Parser.Lex();
5720 if (getLexer().isNot(AsmToken::EndOfStatement))
5721 return reportParseError("unexpected token, expected end of statement");
5722
5723 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5724 getTargetStreamer().emitDirectiveSetSoftFloat();
5725 return false;
5726}
5727
5728bool MipsAsmParser::parseSetHardFloatDirective() {
5729 MCAsmParser &Parser = getParser();
5730 Parser.Lex();
5731 if (getLexer().isNot(AsmToken::EndOfStatement))
5732 return reportParseError("unexpected token, expected end of statement");
5733
5734 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5735 getTargetStreamer().emitDirectiveSetHardFloat();
5736 return false;
5737}
5738
Jack Carterd76b2372013-03-21 21:44:16 +00005739bool MipsAsmParser::parseSetAssignment() {
5740 StringRef Name;
5741 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005742 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005743
5744 if (Parser.parseIdentifier(Name))
5745 reportParseError("expected identifier after .set");
5746
5747 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005748 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005749 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005750
Jack Carter3b2c96e2014-01-22 23:31:38 +00005751 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005752 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005753
Jim Grosbach6f482002015-05-18 18:43:14 +00005754 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005755 Sym->setVariableValue(Value);
5756
5757 return false;
5758}
Jack Carterd0bd6422013-04-18 00:41:53 +00005759
Toma Tabacu26647792014-09-09 12:52:14 +00005760bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005761 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005762 Parser.Lex();
5763 if (getLexer().isNot(AsmToken::EndOfStatement))
5764 return reportParseError("unexpected token, expected end of statement");
5765
5766 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005767 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005768 setAvailableFeatures(
5769 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5770 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005771 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5772
5773 getTargetStreamer().emitDirectiveSetMips0();
5774 return false;
5775}
5776
Toma Tabacu85618b32014-08-19 14:22:52 +00005777bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005778 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005779 Parser.Lex();
5780 if (getLexer().isNot(AsmToken::Equal))
5781 return reportParseError("unexpected token, expected equals sign");
5782
5783 Parser.Lex();
5784 StringRef Arch;
5785 if (Parser.parseIdentifier(Arch))
5786 return reportParseError("expected arch identifier");
5787
5788 StringRef ArchFeatureName =
5789 StringSwitch<StringRef>(Arch)
5790 .Case("mips1", "mips1")
5791 .Case("mips2", "mips2")
5792 .Case("mips3", "mips3")
5793 .Case("mips4", "mips4")
5794 .Case("mips5", "mips5")
5795 .Case("mips32", "mips32")
5796 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005797 .Case("mips32r3", "mips32r3")
5798 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005799 .Case("mips32r6", "mips32r6")
5800 .Case("mips64", "mips64")
5801 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005802 .Case("mips64r3", "mips64r3")
5803 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005804 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005805 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005806 .Case("r4000", "mips3") // This is an implementation of Mips3.
5807 .Default("");
5808
5809 if (ArchFeatureName.empty())
5810 return reportParseError("unsupported architecture");
5811
5812 selectArch(ArchFeatureName);
5813 getTargetStreamer().emitDirectiveSetArch(Arch);
5814 return false;
5815}
5816
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005817bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005818 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005819 Parser.Lex();
5820 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005821 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005822
Matheus Almeida2852af82014-04-22 10:15:54 +00005823 switch (Feature) {
5824 default:
5825 llvm_unreachable("Unimplemented feature");
5826 case Mips::FeatureDSP:
5827 setFeatureBits(Mips::FeatureDSP, "dsp");
5828 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005829 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005830 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00005831 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00005832 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005833 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005834 case Mips::FeatureMips1:
5835 selectArch("mips1");
5836 getTargetStreamer().emitDirectiveSetMips1();
5837 break;
5838 case Mips::FeatureMips2:
5839 selectArch("mips2");
5840 getTargetStreamer().emitDirectiveSetMips2();
5841 break;
5842 case Mips::FeatureMips3:
5843 selectArch("mips3");
5844 getTargetStreamer().emitDirectiveSetMips3();
5845 break;
5846 case Mips::FeatureMips4:
5847 selectArch("mips4");
5848 getTargetStreamer().emitDirectiveSetMips4();
5849 break;
5850 case Mips::FeatureMips5:
5851 selectArch("mips5");
5852 getTargetStreamer().emitDirectiveSetMips5();
5853 break;
5854 case Mips::FeatureMips32:
5855 selectArch("mips32");
5856 getTargetStreamer().emitDirectiveSetMips32();
5857 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005858 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005859 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005860 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005861 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005862 case Mips::FeatureMips32r3:
5863 selectArch("mips32r3");
5864 getTargetStreamer().emitDirectiveSetMips32R3();
5865 break;
5866 case Mips::FeatureMips32r5:
5867 selectArch("mips32r5");
5868 getTargetStreamer().emitDirectiveSetMips32R5();
5869 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005870 case Mips::FeatureMips32r6:
5871 selectArch("mips32r6");
5872 getTargetStreamer().emitDirectiveSetMips32R6();
5873 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005874 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005875 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005876 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005877 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005878 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005879 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005880 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005881 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005882 case Mips::FeatureMips64r3:
5883 selectArch("mips64r3");
5884 getTargetStreamer().emitDirectiveSetMips64R3();
5885 break;
5886 case Mips::FeatureMips64r5:
5887 selectArch("mips64r5");
5888 getTargetStreamer().emitDirectiveSetMips64R5();
5889 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005890 case Mips::FeatureMips64r6:
5891 selectArch("mips64r6");
5892 getTargetStreamer().emitDirectiveSetMips64R6();
5893 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005894 }
5895 return false;
5896}
5897
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005898bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005899 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005900 if (getLexer().isNot(AsmToken::Comma)) {
5901 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005902 return Error(Loc, ErrorStr);
5903 }
5904
Matheus Almeida2852af82014-04-22 10:15:54 +00005905 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005906 return true;
5907}
5908
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005909// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5910// In this class, it is only used for .cprestore.
5911// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5912// MipsTargetELFStreamer and MipsAsmParser.
5913bool MipsAsmParser::isPicAndNotNxxAbi() {
5914 return inPicMode() && !(isABI_N32() || isABI_N64());
5915}
5916
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005917bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005918 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005919 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005920
Toma Tabacudde4c462014-11-06 10:02:45 +00005921 if (inMips16Mode()) {
5922 reportParseError(".cpload is not supported in Mips16 mode");
5923 return false;
5924 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005925
David Blaikie960ea3f2014-06-08 16:18:35 +00005926 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005927 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005928 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5929 reportParseError("expected register containing function address");
5930 return false;
5931 }
5932
David Blaikie960ea3f2014-06-08 16:18:35 +00005933 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5934 if (!RegOpnd.isGPRAsmReg()) {
5935 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005936 return false;
5937 }
5938
Toma Tabacudde4c462014-11-06 10:02:45 +00005939 // If this is not the end of the statement, report an error.
5940 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5941 reportParseError("unexpected token, expected end of statement");
5942 return false;
5943 }
5944
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005945 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005946 return false;
5947}
5948
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005949bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5950 MCAsmParser &Parser = getParser();
5951
5952 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5953 // is used in non-PIC mode.
5954
5955 if (inMips16Mode()) {
5956 reportParseError(".cprestore is not supported in Mips16 mode");
5957 return false;
5958 }
5959
5960 // Get the stack offset value.
5961 const MCExpr *StackOffset;
5962 int64_t StackOffsetVal;
5963 if (Parser.parseExpression(StackOffset)) {
5964 reportParseError("expected stack offset value");
5965 return false;
5966 }
5967
5968 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5969 reportParseError("stack offset is not an absolute expression");
5970 return false;
5971 }
5972
5973 if (StackOffsetVal < 0) {
5974 Warning(Loc, ".cprestore with negative stack offset has no effect");
5975 IsCpRestoreSet = false;
5976 } else {
5977 IsCpRestoreSet = true;
5978 CpRestoreOffset = StackOffsetVal;
5979 }
5980
5981 // If this is not the end of the statement, report an error.
5982 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5983 reportParseError("unexpected token, expected end of statement");
5984 return false;
5985 }
5986
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005987 if (!getTargetStreamer().emitDirectiveCpRestore(
5988 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005989 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005990 Parser.Lex(); // Consume the EndOfStatement.
5991 return false;
5992}
5993
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005994bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005995 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005996 unsigned FuncReg;
5997 unsigned Save;
5998 bool SaveIsReg = true;
5999
Matheus Almeida7e815762014-06-18 13:08:59 +00006000 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006001 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006002 if (ResTy == MatchOperand_NoMatch) {
6003 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00006004 return false;
6005 }
6006
6007 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6008 if (!FuncRegOpnd.isGPRAsmReg()) {
6009 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006010 return false;
6011 }
6012
6013 FuncReg = FuncRegOpnd.getGPR32Reg();
6014 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006015
Toma Tabacu65f10572014-09-16 15:00:52 +00006016 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006017 return true;
6018
Toma Tabacu13964452014-09-04 13:23:44 +00006019 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006020 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00006021 const MCExpr *OffsetExpr;
6022 int64_t OffsetVal;
6023 SMLoc ExprLoc = getLexer().getLoc();
6024
6025 if (Parser.parseExpression(OffsetExpr) ||
6026 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
6027 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00006028 return false;
6029 }
Daniel Sanders5d796282015-09-21 09:26:55 +00006030
6031 Save = OffsetVal;
6032 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00006033 } else {
6034 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6035 if (!SaveOpnd.isGPRAsmReg()) {
6036 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006037 return false;
6038 }
6039 Save = SaveOpnd.getGPR32Reg();
6040 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006041
Toma Tabacu65f10572014-09-16 15:00:52 +00006042 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006043 return true;
6044
Toma Tabacu8874eac2015-02-18 13:46:53 +00006045 const MCExpr *Expr;
6046 if (Parser.parseExpression(Expr)) {
6047 reportParseError("expected expression");
6048 return false;
6049 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006050
Toma Tabacu8874eac2015-02-18 13:46:53 +00006051 if (Expr->getKind() != MCExpr::SymbolRef) {
6052 reportParseError("expected symbol");
6053 return false;
6054 }
6055 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
6056
Daniel Sandersf173dda2015-09-22 10:50:09 +00006057 CpSaveLocation = Save;
6058 CpSaveLocationIsRegister = SaveIsReg;
6059
Toma Tabacu8874eac2015-02-18 13:46:53 +00006060 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
6061 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006062 return false;
6063}
6064
Daniel Sandersf173dda2015-09-22 10:50:09 +00006065bool MipsAsmParser::parseDirectiveCPReturn() {
6066 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
6067 CpSaveLocationIsRegister);
6068 return false;
6069}
6070
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006071bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006072 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006073 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6074 const AsmToken &Tok = Parser.getTok();
6075
6076 if (Tok.getString() == "2008") {
6077 Parser.Lex();
6078 getTargetStreamer().emitDirectiveNaN2008();
6079 return false;
6080 } else if (Tok.getString() == "legacy") {
6081 Parser.Lex();
6082 getTargetStreamer().emitDirectiveNaNLegacy();
6083 return false;
6084 }
6085 }
6086 // If we don't recognize the option passed to the .nan
6087 // directive (e.g. no option or unknown option), emit an error.
6088 reportParseError("invalid option in .nan directive");
6089 return false;
6090}
6091
Jack Carter0b744b32012-10-04 02:29:46 +00006092bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006093 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006094 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00006095 const AsmToken &Tok = Parser.getTok();
6096
6097 if (Tok.getString() == "noat") {
6098 return parseSetNoAtDirective();
6099 } else if (Tok.getString() == "at") {
6100 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00006101 } else if (Tok.getString() == "arch") {
6102 return parseSetArchDirective();
Simon Dardisac9c30c2017-02-01 18:50:24 +00006103 } else if (Tok.getString() == "bopt") {
6104 Warning(Tok.getLoc(), "'bopt' feature is unsupported");
6105 getParser().Lex();
6106 return false;
6107 } else if (Tok.getString() == "nobopt") {
6108 // We're already running in nobopt mode, so nothing to do.
6109 getParser().Lex();
6110 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006111 } else if (Tok.getString() == "fp") {
6112 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006113 } else if (Tok.getString() == "oddspreg") {
6114 return parseSetOddSPRegDirective();
6115 } else if (Tok.getString() == "nooddspreg") {
6116 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006117 } else if (Tok.getString() == "pop") {
6118 return parseSetPopDirective();
6119 } else if (Tok.getString() == "push") {
6120 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00006121 } else if (Tok.getString() == "reorder") {
6122 return parseSetReorderDirective();
6123 } else if (Tok.getString() == "noreorder") {
6124 return parseSetNoReorderDirective();
6125 } else if (Tok.getString() == "macro") {
6126 return parseSetMacroDirective();
6127 } else if (Tok.getString() == "nomacro") {
6128 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00006129 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00006130 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006131 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00006132 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006133 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00006134 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00006135 getTargetStreamer().emitDirectiveSetNoMicroMips();
6136 Parser.eatToEndOfStatement();
6137 return false;
6138 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006139 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00006140 } else if (Tok.getString() == "mips0") {
6141 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00006142 } else if (Tok.getString() == "mips1") {
6143 return parseSetFeature(Mips::FeatureMips1);
6144 } else if (Tok.getString() == "mips2") {
6145 return parseSetFeature(Mips::FeatureMips2);
6146 } else if (Tok.getString() == "mips3") {
6147 return parseSetFeature(Mips::FeatureMips3);
6148 } else if (Tok.getString() == "mips4") {
6149 return parseSetFeature(Mips::FeatureMips4);
6150 } else if (Tok.getString() == "mips5") {
6151 return parseSetFeature(Mips::FeatureMips5);
6152 } else if (Tok.getString() == "mips32") {
6153 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00006154 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006155 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006156 } else if (Tok.getString() == "mips32r3") {
6157 return parseSetFeature(Mips::FeatureMips32r3);
6158 } else if (Tok.getString() == "mips32r5") {
6159 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006160 } else if (Tok.getString() == "mips32r6") {
6161 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006162 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006163 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006164 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006165 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006166 } else if (Tok.getString() == "mips64r3") {
6167 return parseSetFeature(Mips::FeatureMips64r3);
6168 } else if (Tok.getString() == "mips64r5") {
6169 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006170 } else if (Tok.getString() == "mips64r6") {
6171 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00006172 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006173 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006174 } else if (Tok.getString() == "nodsp") {
6175 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00006176 } else if (Tok.getString() == "msa") {
6177 return parseSetMsaDirective();
6178 } else if (Tok.getString() == "nomsa") {
6179 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00006180 } else if (Tok.getString() == "softfloat") {
6181 return parseSetSoftFloatDirective();
6182 } else if (Tok.getString() == "hardfloat") {
6183 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00006184 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00006185 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00006186 parseSetAssignment();
6187 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006188 }
Jack Carter07c818d2013-01-25 01:31:34 +00006189
Jack Carter0b744b32012-10-04 02:29:46 +00006190 return true;
6191}
6192
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006193/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00006194/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006195bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006196 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006197 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006198 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00006199 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00006200 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00006201 return true;
6202
6203 getParser().getStreamer().EmitValue(Value, Size);
6204
6205 if (getLexer().is(AsmToken::EndOfStatement))
6206 break;
6207
Jack Carter07c818d2013-01-25 01:31:34 +00006208 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006209 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00006210 Parser.Lex();
6211 }
6212 }
6213
6214 Parser.Lex();
6215 return false;
6216}
6217
Vladimir Medic4c299852013-11-06 11:27:05 +00006218/// parseDirectiveGpWord
6219/// ::= .gpword local_sym
6220bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006221 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00006222 const MCExpr *Value;
6223 // EmitGPRel32Value requires an expression, so we are using base class
6224 // method to evaluate the expression.
6225 if (getParser().parseExpression(Value))
6226 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00006227 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00006228
Vladimir Medice10c1122013-11-13 13:18:04 +00006229 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006230 return Error(getLexer().getLoc(),
6231 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00006232 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00006233 return false;
6234}
6235
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006236/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00006237/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006238bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006239 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006240 const MCExpr *Value;
6241 // EmitGPRel64Value requires an expression, so we are using base class
6242 // method to evaluate the expression.
6243 if (getParser().parseExpression(Value))
6244 return true;
6245 getParser().getStreamer().EmitGPRel64Value(Value);
6246
6247 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006248 return Error(getLexer().getLoc(),
6249 "unexpected token, expected end of statement");
6250 Parser.Lex(); // Eat EndOfStatement token.
6251 return false;
6252}
6253
6254/// parseDirectiveDtpRelWord
6255/// ::= .dtprelword tls_sym
6256bool MipsAsmParser::parseDirectiveDtpRelWord() {
6257 MCAsmParser &Parser = getParser();
6258 const MCExpr *Value;
6259 // EmitDTPRel32Value requires an expression, so we are using base class
6260 // method to evaluate the expression.
6261 if (getParser().parseExpression(Value))
6262 return true;
6263 getParser().getStreamer().EmitDTPRel32Value(Value);
6264
6265 if (getLexer().isNot(AsmToken::EndOfStatement))
6266 return Error(getLexer().getLoc(),
6267 "unexpected token, expected end of statement");
6268 Parser.Lex(); // Eat EndOfStatement token.
6269 return false;
6270}
6271
6272/// parseDirectiveDtpRelDWord
6273/// ::= .dtpreldword tls_sym
6274bool MipsAsmParser::parseDirectiveDtpRelDWord() {
6275 MCAsmParser &Parser = getParser();
6276 const MCExpr *Value;
6277 // EmitDTPRel64Value requires an expression, so we are using base class
6278 // method to evaluate the expression.
6279 if (getParser().parseExpression(Value))
6280 return true;
6281 getParser().getStreamer().EmitDTPRel64Value(Value);
6282
6283 if (getLexer().isNot(AsmToken::EndOfStatement))
6284 return Error(getLexer().getLoc(),
6285 "unexpected token, expected end of statement");
6286 Parser.Lex(); // Eat EndOfStatement token.
6287 return false;
6288}
6289
6290/// parseDirectiveTpRelWord
6291/// ::= .tprelword tls_sym
6292bool MipsAsmParser::parseDirectiveTpRelWord() {
6293 MCAsmParser &Parser = getParser();
6294 const MCExpr *Value;
6295 // EmitTPRel32Value requires an expression, so we are using base class
6296 // method to evaluate the expression.
6297 if (getParser().parseExpression(Value))
6298 return true;
6299 getParser().getStreamer().EmitTPRel32Value(Value);
6300
6301 if (getLexer().isNot(AsmToken::EndOfStatement))
6302 return Error(getLexer().getLoc(),
6303 "unexpected token, expected end of statement");
6304 Parser.Lex(); // Eat EndOfStatement token.
6305 return false;
6306}
6307
6308/// parseDirectiveTpRelDWord
6309/// ::= .tpreldword tls_sym
6310bool MipsAsmParser::parseDirectiveTpRelDWord() {
6311 MCAsmParser &Parser = getParser();
6312 const MCExpr *Value;
6313 // EmitTPRel64Value requires an expression, so we are using base class
6314 // method to evaluate the expression.
6315 if (getParser().parseExpression(Value))
6316 return true;
6317 getParser().getStreamer().EmitTPRel64Value(Value);
6318
6319 if (getLexer().isNot(AsmToken::EndOfStatement))
6320 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00006321 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00006322 Parser.Lex(); // Eat EndOfStatement token.
6323 return false;
6324}
6325
Jack Carter0cd3c192014-01-06 23:27:31 +00006326bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006327 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00006328 // Get the option token.
6329 AsmToken Tok = Parser.getTok();
6330 // At the moment only identifiers are supported.
6331 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006332 return Error(Parser.getTok().getLoc(),
6333 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00006334 }
6335
6336 StringRef Option = Tok.getIdentifier();
6337
6338 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006339 // MipsAsmParser needs to know if the current PIC mode changes.
6340 IsPicEnabled = false;
6341
Jack Carter0cd3c192014-01-06 23:27:31 +00006342 getTargetStreamer().emitDirectiveOptionPic0();
6343 Parser.Lex();
6344 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006345 return Error(Parser.getTok().getLoc(),
6346 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006347 }
6348 return false;
6349 }
6350
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006351 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006352 // MipsAsmParser needs to know if the current PIC mode changes.
6353 IsPicEnabled = true;
6354
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006355 getTargetStreamer().emitDirectiveOptionPic2();
6356 Parser.Lex();
6357 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006358 return Error(Parser.getTok().getLoc(),
6359 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006360 }
6361 return false;
6362 }
6363
Jack Carter0cd3c192014-01-06 23:27:31 +00006364 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00006365 Warning(Parser.getTok().getLoc(),
6366 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00006367 Parser.eatToEndOfStatement();
6368 return false;
6369}
6370
Toma Tabacu9ca50962015-04-16 09:53:47 +00006371/// parseInsnDirective
6372/// ::= .insn
6373bool MipsAsmParser::parseInsnDirective() {
6374 // If this is not the end of the statement, report an error.
6375 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6376 reportParseError("unexpected token, expected end of statement");
6377 return false;
6378 }
6379
6380 // The actual label marking happens in
6381 // MipsELFStreamer::createPendingLabelRelocs().
6382 getTargetStreamer().emitDirectiveInsn();
6383
6384 getParser().Lex(); // Eat EndOfStatement token.
6385 return false;
6386}
6387
Simon Atanasyanbe186202016-02-11 06:45:54 +00006388/// parseSSectionDirective
6389/// ::= .sbss
6390/// ::= .sdata
6391bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
6392 // If this is not the end of the statement, report an error.
6393 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6394 reportParseError("unexpected token, expected end of statement");
6395 return false;
6396 }
6397
6398 MCSection *ELFSection = getContext().getELFSection(
6399 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
6400 getParser().getStreamer().SwitchSection(ELFSection);
6401
6402 getParser().Lex(); // Eat EndOfStatement token.
6403 return false;
6404}
6405
Daniel Sanders7e527422014-07-10 13:38:23 +00006406/// parseDirectiveModule
6407/// ::= .module oddspreg
6408/// ::= .module nooddspreg
6409/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00006410/// ::= .module softfloat
6411/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006412bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006413 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006414 MCAsmLexer &Lexer = getLexer();
6415 SMLoc L = Lexer.getLoc();
6416
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006417 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006418 // TODO : get a better message.
6419 reportParseError(".module directive must appear before any code");
6420 return false;
6421 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006422
Toma Tabacuc405c822015-01-23 10:40:19 +00006423 StringRef Option;
6424 if (Parser.parseIdentifier(Option)) {
6425 reportParseError("expected .module option identifier");
6426 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006427 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006428
Toma Tabacuc405c822015-01-23 10:40:19 +00006429 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006430 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006431
Toma Tabacu3c499582015-06-25 10:56:57 +00006432 // Synchronize the abiflags information with the FeatureBits information we
6433 // changed above.
6434 getTargetStreamer().updateABIInfo(*this);
6435
6436 // If printing assembly, use the recently updated abiflags information.
6437 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6438 // emitted at the end).
6439 getTargetStreamer().emitDirectiveModuleOddSPReg();
6440
Toma Tabacuc405c822015-01-23 10:40:19 +00006441 // If this is not the end of the statement, report an error.
6442 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6443 reportParseError("unexpected token, expected end of statement");
6444 return false;
6445 }
6446
6447 return false; // parseDirectiveModule has finished successfully.
6448 } else if (Option == "nooddspreg") {
6449 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006450 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00006451 }
6452
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006453 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006454
Toma Tabacu3c499582015-06-25 10:56:57 +00006455 // Synchronize the abiflags information with the FeatureBits information we
6456 // changed above.
6457 getTargetStreamer().updateABIInfo(*this);
6458
6459 // If printing assembly, use the recently updated abiflags information.
6460 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6461 // emitted at the end).
6462 getTargetStreamer().emitDirectiveModuleOddSPReg();
6463
Toma Tabacuc405c822015-01-23 10:40:19 +00006464 // If this is not the end of the statement, report an error.
6465 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6466 reportParseError("unexpected token, expected end of statement");
6467 return false;
6468 }
6469
6470 return false; // parseDirectiveModule has finished successfully.
6471 } else if (Option == "fp") {
6472 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00006473 } else if (Option == "softfloat") {
6474 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6475
6476 // Synchronize the ABI Flags information with the FeatureBits information we
6477 // updated above.
6478 getTargetStreamer().updateABIInfo(*this);
6479
6480 // If printing assembly, use the recently updated ABI Flags information.
6481 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6482 // emitted later).
6483 getTargetStreamer().emitDirectiveModuleSoftFloat();
6484
6485 // If this is not the end of the statement, report an error.
6486 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6487 reportParseError("unexpected token, expected end of statement");
6488 return false;
6489 }
6490
6491 return false; // parseDirectiveModule has finished successfully.
6492 } else if (Option == "hardfloat") {
6493 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6494
6495 // Synchronize the ABI Flags information with the FeatureBits information we
6496 // updated above.
6497 getTargetStreamer().updateABIInfo(*this);
6498
6499 // If printing assembly, use the recently updated ABI Flags information.
6500 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6501 // emitted later).
6502 getTargetStreamer().emitDirectiveModuleHardFloat();
6503
6504 // If this is not the end of the statement, report an error.
6505 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6506 reportParseError("unexpected token, expected end of statement");
6507 return false;
6508 }
6509
6510 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00006511 } else {
6512 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
6513 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006514}
6515
6516/// parseDirectiveModuleFP
6517/// ::= =32
6518/// ::= =xx
6519/// ::= =64
6520bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006521 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006522 MCAsmLexer &Lexer = getLexer();
6523
6524 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006525 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006526 return false;
6527 }
6528 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006529
Daniel Sanders7e527422014-07-10 13:38:23 +00006530 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006531 if (!parseFpABIValue(FpABI, ".module"))
6532 return false;
6533
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006534 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006535 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006536 return false;
6537 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006538
Toma Tabacua64e5402015-06-25 12:44:38 +00006539 // Synchronize the abiflags information with the FeatureBits information we
6540 // changed above.
6541 getTargetStreamer().updateABIInfo(*this);
6542
6543 // If printing assembly, use the recently updated abiflags information.
6544 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6545 // emitted at the end).
6546 getTargetStreamer().emitDirectiveModuleFP();
6547
Daniel Sanders7e527422014-07-10 13:38:23 +00006548 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006549 return false;
6550}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006551
Daniel Sanders7e527422014-07-10 13:38:23 +00006552bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006553 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006554 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006555 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006556 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006557
6558 if (Lexer.is(AsmToken::Identifier)) {
6559 StringRef Value = Parser.getTok().getString();
6560 Parser.Lex();
6561
6562 if (Value != "xx") {
6563 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6564 return false;
6565 }
6566
6567 if (!isABI_O32()) {
6568 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
6569 return false;
6570 }
6571
Daniel Sanders7e527422014-07-10 13:38:23 +00006572 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006573 if (ModuleLevelOptions) {
6574 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6575 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6576 } else {
6577 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6578 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6579 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006580 return true;
6581 }
6582
6583 if (Lexer.is(AsmToken::Integer)) {
6584 unsigned Value = Parser.getTok().getIntVal();
6585 Parser.Lex();
6586
6587 if (Value != 32 && Value != 64) {
6588 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6589 return false;
6590 }
6591
6592 if (Value == 32) {
6593 if (!isABI_O32()) {
6594 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6595 return false;
6596 }
6597
Daniel Sanders7e527422014-07-10 13:38:23 +00006598 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006599 if (ModuleLevelOptions) {
6600 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6601 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6602 } else {
6603 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6604 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6605 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006606 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006607 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006608 if (ModuleLevelOptions) {
6609 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6610 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6611 } else {
6612 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6613 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6614 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006615 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006616
Daniel Sanders7e527422014-07-10 13:38:23 +00006617 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006618 }
6619
6620 return false;
6621}
6622
Jack Carter0b744b32012-10-04 02:29:46 +00006623bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006624 // This returns false if this function recognizes the directive
6625 // regardless of whether it is successfully handles or reports an
6626 // error. Otherwise it returns true to give the generic parser a
6627 // chance at recognizing it.
6628
Rafael Espindola961d4692014-11-11 05:18:41 +00006629 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006630 StringRef IDVal = DirectiveID.getString();
6631
Nirav Dave996fc132016-05-05 14:15:46 +00006632 if (IDVal == ".cpload") {
6633 parseDirectiveCpLoad(DirectiveID.getLoc());
6634 return false;
6635 }
6636 if (IDVal == ".cprestore") {
6637 parseDirectiveCpRestore(DirectiveID.getLoc());
6638 return false;
6639 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006640 if (IDVal == ".dword") {
6641 parseDataDirective(8, DirectiveID.getLoc());
6642 return false;
6643 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006644 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006645 StringRef SymbolName;
6646
6647 if (Parser.parseIdentifier(SymbolName)) {
6648 reportParseError("expected identifier after .ent");
6649 return false;
6650 }
6651
6652 // There's an undocumented extension that allows an integer to
6653 // follow the name of the procedure which AFAICS is ignored by GAS.
6654 // Example: .ent foo,2
6655 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6656 if (getLexer().isNot(AsmToken::Comma)) {
6657 // Even though we accept this undocumented extension for compatibility
6658 // reasons, the additional integer argument does not actually change
6659 // the behaviour of the '.ent' directive, so we would like to discourage
6660 // its use. We do this by not referring to the extended version in
6661 // error messages which are not directly related to its use.
6662 reportParseError("unexpected token, expected end of statement");
6663 return false;
6664 }
6665 Parser.Lex(); // Eat the comma.
6666 const MCExpr *DummyNumber;
6667 int64_t DummyNumberVal;
6668 // If the user was explicitly trying to use the extended version,
6669 // we still give helpful extension-related error messages.
6670 if (Parser.parseExpression(DummyNumber)) {
6671 reportParseError("expected number after comma");
6672 return false;
6673 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006674 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006675 reportParseError("expected an absolute expression after comma");
6676 return false;
6677 }
6678 }
6679
6680 // If this is not the end of the statement, report an error.
6681 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6682 reportParseError("unexpected token, expected end of statement");
6683 return false;
6684 }
6685
Jim Grosbach6f482002015-05-18 18:43:14 +00006686 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006687
6688 getTargetStreamer().emitDirectiveEnt(*Sym);
6689 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006690 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006691 return false;
6692 }
6693
Jack Carter07c818d2013-01-25 01:31:34 +00006694 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006695 StringRef SymbolName;
6696
6697 if (Parser.parseIdentifier(SymbolName)) {
6698 reportParseError("expected identifier after .end");
6699 return false;
6700 }
6701
6702 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6703 reportParseError("unexpected token, expected end of statement");
6704 return false;
6705 }
6706
6707 if (CurrentFn == nullptr) {
6708 reportParseError(".end used without .ent");
6709 return false;
6710 }
6711
6712 if ((SymbolName != CurrentFn->getName())) {
6713 reportParseError(".end symbol does not match .ent symbol");
6714 return false;
6715 }
6716
6717 getTargetStreamer().emitDirectiveEnd(SymbolName);
6718 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006719 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006720 return false;
6721 }
6722
Jack Carter07c818d2013-01-25 01:31:34 +00006723 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006724 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6725 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006726 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006727 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6728 reportParseError("expected stack register");
6729 return false;
6730 }
6731
6732 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6733 if (!StackRegOpnd.isGPRAsmReg()) {
6734 reportParseError(StackRegOpnd.getStartLoc(),
6735 "expected general purpose register");
6736 return false;
6737 }
6738 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6739
6740 if (Parser.getTok().is(AsmToken::Comma))
6741 Parser.Lex();
6742 else {
6743 reportParseError("unexpected token, expected comma");
6744 return false;
6745 }
6746
6747 // Parse the frame size.
6748 const MCExpr *FrameSize;
6749 int64_t FrameSizeVal;
6750
6751 if (Parser.parseExpression(FrameSize)) {
6752 reportParseError("expected frame size value");
6753 return false;
6754 }
6755
Jim Grosbach13760bd2015-05-30 01:25:56 +00006756 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006757 reportParseError("frame size not an absolute expression");
6758 return false;
6759 }
6760
6761 if (Parser.getTok().is(AsmToken::Comma))
6762 Parser.Lex();
6763 else {
6764 reportParseError("unexpected token, expected comma");
6765 return false;
6766 }
6767
6768 // Parse the return register.
6769 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006770 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006771 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6772 reportParseError("expected return register");
6773 return false;
6774 }
6775
6776 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6777 if (!ReturnRegOpnd.isGPRAsmReg()) {
6778 reportParseError(ReturnRegOpnd.getStartLoc(),
6779 "expected general purpose register");
6780 return false;
6781 }
6782
6783 // If this is not the end of the statement, report an error.
6784 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6785 reportParseError("unexpected token, expected end of statement");
6786 return false;
6787 }
6788
6789 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6790 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006791 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006792 return false;
6793 }
6794
Jack Carter07c818d2013-01-25 01:31:34 +00006795 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006796 parseDirectiveSet();
6797 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006798 }
6799
Daniel Sandersd97a6342014-08-13 10:07:34 +00006800 if (IDVal == ".mask" || IDVal == ".fmask") {
6801 // .mask bitmask, frame_offset
6802 // bitmask: One bit for each register used.
6803 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6804 // first register is expected to be saved.
6805 // Examples:
6806 // .mask 0x80000000, -4
6807 // .fmask 0x80000000, -4
6808 //
Jack Carterbe332172012-09-07 00:48:02 +00006809
Daniel Sandersd97a6342014-08-13 10:07:34 +00006810 // Parse the bitmask
6811 const MCExpr *BitMask;
6812 int64_t BitMaskVal;
6813
6814 if (Parser.parseExpression(BitMask)) {
6815 reportParseError("expected bitmask value");
6816 return false;
6817 }
6818
Jim Grosbach13760bd2015-05-30 01:25:56 +00006819 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006820 reportParseError("bitmask not an absolute expression");
6821 return false;
6822 }
6823
6824 if (Parser.getTok().is(AsmToken::Comma))
6825 Parser.Lex();
6826 else {
6827 reportParseError("unexpected token, expected comma");
6828 return false;
6829 }
6830
6831 // Parse the frame_offset
6832 const MCExpr *FrameOffset;
6833 int64_t FrameOffsetVal;
6834
6835 if (Parser.parseExpression(FrameOffset)) {
6836 reportParseError("expected frame offset value");
6837 return false;
6838 }
6839
Jim Grosbach13760bd2015-05-30 01:25:56 +00006840 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006841 reportParseError("frame offset not an absolute expression");
6842 return false;
6843 }
6844
6845 // If this is not the end of the statement, report an error.
6846 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6847 reportParseError("unexpected token, expected end of statement");
6848 return false;
6849 }
6850
6851 if (IDVal == ".mask")
6852 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6853 else
6854 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006855 return false;
6856 }
6857
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006858 if (IDVal == ".nan")
6859 return parseDirectiveNaN();
6860
Jack Carter07c818d2013-01-25 01:31:34 +00006861 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006862 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006863 return false;
6864 }
6865
Rafael Espindolab59fb732014-03-28 18:50:26 +00006866 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006867 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006868 return false;
6869 }
6870
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006871 if (IDVal == ".dtprelword") {
6872 parseDirectiveDtpRelWord();
6873 return false;
6874 }
6875
6876 if (IDVal == ".dtpreldword") {
6877 parseDirectiveDtpRelDWord();
6878 return false;
6879 }
6880
6881 if (IDVal == ".tprelword") {
6882 parseDirectiveTpRelWord();
6883 return false;
6884 }
6885
6886 if (IDVal == ".tpreldword") {
6887 parseDirectiveTpRelDWord();
6888 return false;
6889 }
6890
Jack Carter07c818d2013-01-25 01:31:34 +00006891 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006892 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006893 return false;
6894 }
6895
Scott Egertond1aeb052016-02-15 16:11:51 +00006896 if (IDVal == ".hword") {
6897 parseDataDirective(2, DirectiveID.getLoc());
6898 return false;
6899 }
6900
Nirav Dave996fc132016-05-05 14:15:46 +00006901 if (IDVal == ".option") {
6902 parseDirectiveOption();
6903 return false;
6904 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006905
6906 if (IDVal == ".abicalls") {
6907 getTargetStreamer().emitDirectiveAbiCalls();
6908 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006909 Error(Parser.getTok().getLoc(),
6910 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006911 }
6912 return false;
6913 }
6914
Nirav Dave996fc132016-05-05 14:15:46 +00006915 if (IDVal == ".cpsetup") {
6916 parseDirectiveCPSetup();
6917 return false;
6918 }
6919 if (IDVal == ".cpreturn") {
6920 parseDirectiveCPReturn();
6921 return false;
6922 }
6923 if (IDVal == ".module") {
6924 parseDirectiveModule();
6925 return false;
6926 }
6927 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6928 parseInternalDirectiveReallowModule();
6929 return false;
6930 }
6931 if (IDVal == ".insn") {
6932 parseInsnDirective();
6933 return false;
6934 }
6935 if (IDVal == ".sbss") {
6936 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6937 return false;
6938 }
6939 if (IDVal == ".sdata") {
6940 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6941 return false;
6942 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006943
Rafael Espindola870c4e92012-01-11 03:56:41 +00006944 return true;
6945}
6946
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006947bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6948 // If this is not the end of the statement, report an error.
6949 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6950 reportParseError("unexpected token, expected end of statement");
6951 return false;
6952 }
6953
6954 getTargetStreamer().reallowModuleDirective();
6955
6956 getParser().Lex(); // Eat EndOfStatement token.
6957 return false;
6958}
6959
Rafael Espindola870c4e92012-01-11 03:56:41 +00006960extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00006961 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
6962 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
6963 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
6964 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00006965}
Jack Carterb4dbc172012-09-05 23:34:03 +00006966
6967#define GET_REGISTER_MATCHER
6968#define GET_MATCHER_IMPLEMENTATION
6969#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00006970
6971bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
6972 // Find the appropriate table for this asm variant.
6973 const MatchEntry *Start, *End;
6974 switch (VariantID) {
6975 default: llvm_unreachable("invalid variant!");
6976 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
6977 }
6978 // Search the table.
6979 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
6980 return MnemonicRange.first != MnemonicRange.second;
6981}