blob: 504a4983036b5d5ccd3b331d0d69160f7998cd2f [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
David Blaikie960ea3f2014-06-08 16:18:35 +0000172 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
173 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000174
Craig Topper56c590a2014-04-29 07:58:02 +0000175 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000176
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000177 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
178 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000179 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000180 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000181 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
182 SMLoc S);
183 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
184 OperandMatchResultTy parseImm(OperandVector &Operands);
185 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
186 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000187 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
188 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
189 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000190
David Blaikie960ea3f2014-06-08 16:18:35 +0000191 bool searchSymbolAlias(OperandVector &Operands);
192
Toma Tabacu13964452014-09-04 13:23:44 +0000193 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000194
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000195 enum MacroExpanderResultTy {
196 MER_NotAMacro,
197 MER_Success,
198 MER_Fail,
199 };
Jack Carter30a59822012-10-04 04:03:53 +0000200
Matheus Almeida3813d572014-06-19 14:39:14 +0000201 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000202 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
203 MCStreamer &Out,
204 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000205
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000206 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
207 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000208
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000209 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000210 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000211 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000212
Toma Tabacuf712ede2015-06-17 14:31:51 +0000213 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
214 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000215 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000216
Toma Tabacu00e98672015-05-01 12:19:27 +0000217 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000219
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000220 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
221 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000222 SMLoc IDLoc, MCStreamer &Out,
223 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000224
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000225 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
226 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000227
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000228 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000229 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
230
231 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
232 const MCSubtargetInfo *STI, bool IsImmOpnd);
233
234 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000236
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000237 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
238 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000239
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000240 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
241 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000242
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000243 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000245
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000246 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000248
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000249 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
250 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000251 const bool Signed);
252
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000253 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000254 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000255
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000256 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
257 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000258
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000259 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
260 const MCSubtargetInfo *STI);
261
262 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000263 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000264
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000265 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000266 MCStreamer &Out, const MCSubtargetInfo *STI);
267 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
268 const MCSubtargetInfo *STI);
269 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
270 const MCSubtargetInfo *STI);
271 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
272 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000273
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000274 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
275 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000276
Simon Dardisaff4d142016-10-18 14:28:00 +0000277 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
278 const MCSubtargetInfo *STI, bool IsLoad);
279
Simon Dardis43115a12016-11-21 20:30:41 +0000280 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
281 const MCSubtargetInfo *STI);
282
283 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
284 const MCSubtargetInfo *STI);
285
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000286 bool reportParseError(Twine ErrorMsg);
287 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000288
Jack Carterb5cf5902013-04-17 00:18:04 +0000289 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000290
291 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000292 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000293 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000294 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000295 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000296 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000297 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000298 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000299 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000300 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000301 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000302 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000303 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000304 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000305
306 bool parseSetAtDirective();
307 bool parseSetNoAtDirective();
308 bool parseSetMacroDirective();
309 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000310 bool parseSetMsaDirective();
311 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000312 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000313 bool parseSetReorderDirective();
314 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000315 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000316 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000317 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000318 bool parseSetOddSPRegDirective();
319 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000320 bool parseSetPopDirective();
321 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000322 bool parseSetSoftFloatDirective();
323 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000324
Jack Carterd76b2372013-03-21 21:44:16 +0000325 bool parseSetAssignment();
326
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000327 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000328 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000329 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000330 bool parseDirectiveDtpRelWord();
331 bool parseDirectiveDtpRelDWord();
332 bool parseDirectiveTpRelWord();
333 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000334 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000335 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000336 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
337 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000338
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000339 bool parseInternalDirectiveReallowModule();
340
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000341 bool eatComma(StringRef ErrorStr);
342
Jack Carter1ac53222013-02-20 23:11:17 +0000343 int matchCPURegisterName(StringRef Symbol);
344
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000345 int matchHWRegsRegisterName(StringRef Symbol);
346
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000347 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000348
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000349 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000350
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000351 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000352
Jack Carter5dc8ac92013-09-25 23:50:44 +0000353 int matchMSA128RegisterName(StringRef Name);
354
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000355 int matchMSA128CtrlRegisterName(StringRef Name);
356
Jack Carterd0bd6422013-04-18 00:41:53 +0000357 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000358
Toma Tabacu89a712b2015-04-15 10:48:56 +0000359 /// Returns the internal register number for the current AT. Also checks if
360 /// the current AT is unavailable (set to $0) and gives an error if it is.
361 /// This should be used in pseudo-instruction expansions which need AT.
362 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000363
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000364 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
365 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000366
367 // Helper function that checks if the value of a vector index is within the
368 // boundaries of accepted values for each RegisterKind
369 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
370 bool validateMSAIndex(int Val, int RegKind);
371
Daniel Sandersf0df2212014-08-04 12:20:00 +0000372 // Selects a new architecture by updating the FeatureBits with the necessary
373 // info including implied dependencies.
374 // Internally, it clears all the feature bits related to *any* architecture
375 // and selects the new one using the ToggleFeature functionality of the
376 // MCSubtargetInfo object that handles implied dependencies. The reason we
377 // clear all the arch related bits manually is because ToggleFeature only
378 // clears the features that imply the feature being cleared and not the
379 // features implied by the feature being cleared. This is easier to see
380 // with an example:
381 // --------------------------------------------------
382 // | Feature | Implies |
383 // | -------------------------------------------------|
384 // | FeatureMips1 | None |
385 // | FeatureMips2 | FeatureMips1 |
386 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
387 // | FeatureMips4 | FeatureMips3 |
388 // | ... | |
389 // --------------------------------------------------
390 //
391 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
392 // FeatureMipsGP64 | FeatureMips1)
393 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
394 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000395 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000396 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000397 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
398 STI.setFeatureBits(FeatureBits);
399 setAvailableFeatures(
400 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000401 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000402 }
403
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000404 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000405 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000406 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000407 setAvailableFeatures(
408 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000409 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000410 }
411 }
412
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000413 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000414 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000415 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000416 setAvailableFeatures(
417 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000418 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000419 }
420 }
421
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000422 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
423 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000424 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000425 }
426
427 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
428 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000429 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000430 }
431
Rafael Espindola870c4e92012-01-11 03:56:41 +0000432public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000433 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000434 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000435 Match_RequiresDifferentOperands,
436 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000437 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000438 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000439 Match_NonZeroOperandForSync,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000440#define GET_OPERAND_DIAGNOSTIC_TYPES
441#include "MipsGenAsmMatcher.inc"
442#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000443 };
444
Akira Hatanakab11ef082015-11-14 06:35:56 +0000445 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000446 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000447 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000448 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
449 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000450 MCAsmParserExtension::Initialize(parser);
451
Toma Tabacu11e14a92015-04-21 11:50:52 +0000452 parser.addAliasForDirective(".asciiz", ".asciz");
453
Jack Carterb4dbc172012-09-05 23:34:03 +0000454 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000455 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000456
Toma Tabacu9db22db2014-09-09 10:15:38 +0000457 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000458 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000459 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000460
Toma Tabacu9db22db2014-09-09 10:15:38 +0000461 // Create an assembler options environment for the user to modify.
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 Sanders5a1449d2014-02-20 14:58:19 +0000464
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000465 getTargetStreamer().updateABIInfo(*this);
466
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000467 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000468 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000469
470 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000471
Rafael Espindola699281c2016-05-18 11:58:50 +0000472 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000473
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000474 IsCpRestoreSet = false;
475 CpRestoreOffset = -1;
476
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000477 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000478 if ((TheTriple.getArch() == Triple::mips) ||
479 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000480 IsLittleEndian = false;
481 else
482 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000483 }
484
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000485 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
486 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
487
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000488 bool isGP64bit() const {
489 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
490 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000491
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000492 bool isFP64bit() const {
493 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
494 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000495
Eric Christophera5762812015-01-26 17:33:46 +0000496 const MipsABIInfo &getABI() const { return ABI; }
497 bool isABI_N32() const { return ABI.IsN32(); }
498 bool isABI_N64() const { return ABI.IsN64(); }
499 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000500 bool isABI_FPXX() const {
501 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
502 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000503
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000504 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000505 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000506 }
507
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000508 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000509 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000510 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000511
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000512 bool hasMips1() const {
513 return getSTI().getFeatureBits()[Mips::FeatureMips1];
514 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000515
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000516 bool hasMips2() const {
517 return getSTI().getFeatureBits()[Mips::FeatureMips2];
518 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000519
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000520 bool hasMips3() const {
521 return getSTI().getFeatureBits()[Mips::FeatureMips3];
522 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000523
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000524 bool hasMips4() const {
525 return getSTI().getFeatureBits()[Mips::FeatureMips4];
526 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000527
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000528 bool hasMips5() const {
529 return getSTI().getFeatureBits()[Mips::FeatureMips5];
530 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000531
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000532 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000533 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000534 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000535
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000536 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000537 return getSTI().getFeatureBits()[Mips::FeatureMips64];
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 hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000541 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
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 hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000545 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000546 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000547
Daniel Sanders17793142015-02-18 16:24:50 +0000548 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000549 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000550 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000551
Daniel Sanders17793142015-02-18 16:24:50 +0000552 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000553 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
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 hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000557 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
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 hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000561 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000562 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000563
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000564 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000565 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000566 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000567
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000568 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000569 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000570 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000571
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000572 bool hasDSP() const {
573 return getSTI().getFeatureBits()[Mips::FeatureDSP];
574 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000575
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000576 bool hasDSPR2() const {
577 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
578 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000579
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000580 bool hasDSPR3() const {
581 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
582 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000583
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000584 bool hasMSA() const {
585 return getSTI().getFeatureBits()[Mips::FeatureMSA];
586 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000587
Kai Nackee0245392015-01-27 19:11:28 +0000588 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000589 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000590 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000591
Daniel Sandersa6994442015-08-18 12:33:54 +0000592 bool inPicMode() {
593 return IsPicEnabled;
594 }
595
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000596 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000597 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000598 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000599
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000600 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000601 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000602 }
603
Eric Christophere8ae3e32015-05-07 23:10:21 +0000604 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000605 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000606 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000607
Toma Tabacud9d344b2015-04-27 14:05:04 +0000608 /// Warn if RegIndex is the same as the current AT.
609 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000610
611 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000612
613 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000614
615 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
616 AsmToken::TokenKind OperatorToken,
617 MCContext &Ctx) override {
618 switch(OperatorToken) {
619 default:
620 llvm_unreachable("Unknown token");
621 return nullptr;
622 case AsmToken::PercentCall16:
623 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
624 case AsmToken::PercentCall_Hi:
625 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
626 case AsmToken::PercentCall_Lo:
627 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
628 case AsmToken::PercentDtprel_Hi:
629 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
630 case AsmToken::PercentDtprel_Lo:
631 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
632 case AsmToken::PercentGot:
633 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
634 case AsmToken::PercentGot_Disp:
635 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
636 case AsmToken::PercentGot_Hi:
637 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
638 case AsmToken::PercentGot_Lo:
639 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
640 case AsmToken::PercentGot_Ofst:
641 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
642 case AsmToken::PercentGot_Page:
643 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
644 case AsmToken::PercentGottprel:
645 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
646 case AsmToken::PercentGp_Rel:
647 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
648 case AsmToken::PercentHi:
649 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
650 case AsmToken::PercentHigher:
651 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
652 case AsmToken::PercentHighest:
653 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
654 case AsmToken::PercentLo:
655 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
656 case AsmToken::PercentNeg:
657 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
658 case AsmToken::PercentPcrel_Hi:
659 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
660 case AsmToken::PercentPcrel_Lo:
661 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
662 case AsmToken::PercentTlsgd:
663 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
664 case AsmToken::PercentTlsldm:
665 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
666 case AsmToken::PercentTprel_Hi:
667 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
668 case AsmToken::PercentTprel_Lo:
669 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
670 }
671 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000672};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000673
674/// MipsOperand - Instances of this class represent a parsed Mips machine
675/// instruction.
676class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000677public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000678 /// Broad categories of register classes
679 /// The exact class is finalized by the render method.
680 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000681 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000682 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000683 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000684 RegKind_FCC = 4, /// FCC
685 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
686 RegKind_MSACtrl = 16, /// MSA control registers
687 RegKind_COP2 = 32, /// COP2
688 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
689 /// context).
690 RegKind_CCR = 128, /// CCR
691 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000692 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000693 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000694 /// Potentially any (e.g. $1)
695 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
696 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000697 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000698 };
699
700private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000701 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000702 k_Immediate, /// An immediate (possibly involving symbol references)
703 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000704 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000705 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000706 k_RegList, /// A physical register list
707 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000708 } Kind;
709
David Blaikie960ea3f2014-06-08 16:18:35 +0000710public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000711 MipsOperand(KindTy K, MipsAsmParser &Parser)
712 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
713
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000714 ~MipsOperand() override {
715 switch (Kind) {
716 case k_Immediate:
717 break;
718 case k_Memory:
719 delete Mem.Base;
720 break;
721 case k_RegList:
722 delete RegList.List;
723 case k_RegisterIndex:
724 case k_Token:
725 case k_RegPair:
726 break;
727 }
728 }
729
David Blaikie960ea3f2014-06-08 16:18:35 +0000730private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000731 /// For diagnostics, and checking the assembler temporary
732 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000733
Eric Christopher8996c5d2013-03-15 00:42:55 +0000734 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000735 const char *Data;
736 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000737 };
738
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000739 struct RegIdxOp {
740 unsigned Index; /// Index into the register class
741 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000742 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000743 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000744 };
745
746 struct ImmOp {
747 const MCExpr *Val;
748 };
749
750 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000751 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000752 const MCExpr *Off;
753 };
754
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000755 struct RegListOp {
756 SmallVector<unsigned, 10> *List;
757 };
758
Jack Carterb4dbc172012-09-05 23:34:03 +0000759 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000760 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000761 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000762 struct ImmOp Imm;
763 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000764 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000765 };
766
767 SMLoc StartLoc, EndLoc;
768
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000769 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000770 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
771 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000772 const MCRegisterInfo *RegInfo,
773 SMLoc S, SMLoc E,
774 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000775 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000776 Op->RegIdx.Index = Index;
777 Op->RegIdx.RegInfo = RegInfo;
778 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000779 Op->RegIdx.Tok.Data = Str.data();
780 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000781 Op->StartLoc = S;
782 Op->EndLoc = E;
783 return Op;
784 }
785
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000786public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000787 /// Coerce the register to GPR32 and return the real register for the current
788 /// target.
789 unsigned getGPR32Reg() const {
790 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000791 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000792 unsigned ClassID = Mips::GPR32RegClassID;
793 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000794 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000795
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000796 /// Coerce the register to GPR32 and return the real register for the current
797 /// target.
798 unsigned getGPRMM16Reg() const {
799 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
800 unsigned ClassID = Mips::GPR32RegClassID;
801 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
802 }
803
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000804 /// Coerce the register to GPR64 and return the real register for the current
805 /// target.
806 unsigned getGPR64Reg() const {
807 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
808 unsigned ClassID = Mips::GPR64RegClassID;
809 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000810 }
811
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000812private:
813 /// Coerce the register to AFGR64 and return the real register for the current
814 /// target.
815 unsigned getAFGR64Reg() const {
816 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
817 if (RegIdx.Index % 2 != 0)
818 AsmParser.Warning(StartLoc, "Float register should be even.");
819 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
820 .getRegister(RegIdx.Index / 2);
821 }
822
823 /// Coerce the register to FGR64 and return the real register for the current
824 /// target.
825 unsigned getFGR64Reg() const {
826 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
827 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
828 .getRegister(RegIdx.Index);
829 }
830
831 /// Coerce the register to FGR32 and return the real register for the current
832 /// target.
833 unsigned getFGR32Reg() const {
834 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
835 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
836 .getRegister(RegIdx.Index);
837 }
838
839 /// Coerce the register to FGRH32 and return the real register for the current
840 /// target.
841 unsigned getFGRH32Reg() const {
842 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
843 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
844 .getRegister(RegIdx.Index);
845 }
846
847 /// Coerce the register to FCC and return the real register for the current
848 /// target.
849 unsigned getFCCReg() const {
850 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
851 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
852 .getRegister(RegIdx.Index);
853 }
854
855 /// Coerce the register to MSA128 and return the real register for the current
856 /// target.
857 unsigned getMSA128Reg() const {
858 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
859 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
860 // identical
861 unsigned ClassID = Mips::MSA128BRegClassID;
862 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
863 }
864
865 /// Coerce the register to MSACtrl and return the real register for the
866 /// current target.
867 unsigned getMSACtrlReg() const {
868 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
869 unsigned ClassID = Mips::MSACtrlRegClassID;
870 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
871 }
872
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000873 /// Coerce the register to COP0 and return the real register for the
874 /// current target.
875 unsigned getCOP0Reg() const {
876 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
877 unsigned ClassID = Mips::COP0RegClassID;
878 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
879 }
880
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000881 /// Coerce the register to COP2 and return the real register for the
882 /// current target.
883 unsigned getCOP2Reg() const {
884 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
885 unsigned ClassID = Mips::COP2RegClassID;
886 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
887 }
888
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000889 /// Coerce the register to COP3 and return the real register for the
890 /// current target.
891 unsigned getCOP3Reg() const {
892 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
893 unsigned ClassID = Mips::COP3RegClassID;
894 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
895 }
896
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000897 /// Coerce the register to ACC64DSP and return the real register for the
898 /// current target.
899 unsigned getACC64DSPReg() const {
900 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
901 unsigned ClassID = Mips::ACC64DSPRegClassID;
902 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
903 }
904
905 /// Coerce the register to HI32DSP and return the real register for the
906 /// current target.
907 unsigned getHI32DSPReg() const {
908 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
909 unsigned ClassID = Mips::HI32DSPRegClassID;
910 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
911 }
912
913 /// Coerce the register to LO32DSP and return the real register for the
914 /// current target.
915 unsigned getLO32DSPReg() const {
916 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
917 unsigned ClassID = Mips::LO32DSPRegClassID;
918 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
919 }
920
921 /// Coerce the register to CCR and return the real register for the
922 /// current target.
923 unsigned getCCRReg() const {
924 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
925 unsigned ClassID = Mips::CCRRegClassID;
926 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
927 }
928
929 /// Coerce the register to HWRegs and return the real register for the
930 /// current target.
931 unsigned getHWRegsReg() const {
932 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
933 unsigned ClassID = Mips::HWRegsRegClassID;
934 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
935 }
936
937public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000938 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000939 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000940 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000941 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000942 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000943 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000944 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000945 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000946 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000947
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000948 void addRegOperands(MCInst &Inst, unsigned N) const {
949 llvm_unreachable("Use a custom parser instead");
950 }
951
Daniel Sanders21bce302014-04-01 12:35:23 +0000952 /// Render the operand to an MCInst as a GPR32
953 /// Asserts if the wrong number of operands are requested, or the operand
954 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000955 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
956 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000957 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000958 }
959
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000960 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
961 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000962 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000963 }
964
Jozef Kolek1904fa22014-11-24 14:25:53 +0000965 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
966 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000967 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000968 }
969
Zoran Jovanovic41688672015-02-10 16:36:20 +0000970 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
971 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000972 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000973 }
974
Daniel Sanders21bce302014-04-01 12:35:23 +0000975 /// Render the operand to an MCInst as a GPR64
976 /// Asserts if the wrong number of operands are requested, or the operand
977 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000978 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
979 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000980 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000981 }
982
983 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
984 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000985 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000986 }
987
988 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
989 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000990 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000991 }
992
993 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
994 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000995 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000996 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +0000997 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000998 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +0000999 AsmParser.getParser().printError(
1000 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1001 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001002 }
1003
1004 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1005 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001006 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001007 }
1008
1009 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1010 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001011 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001012 }
1013
1014 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1015 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001016 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001017 }
1018
1019 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1020 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001021 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001022 }
1023
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001024 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1025 assert(N == 1 && "Invalid number of operands!");
1026 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1027 }
1028
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001029 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1030 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001031 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001032 }
1033
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001034 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1035 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001036 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001037 }
1038
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001039 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1040 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001041 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001042 }
1043
1044 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1045 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001046 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001047 }
1048
1049 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1050 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001051 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001052 }
1053
1054 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1055 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001056 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001057 }
1058
1059 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1060 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001061 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001062 }
1063
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001064 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001065 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1066 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001067 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001068 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001069 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001070 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001071 Inst.addOperand(MCOperand::createImm(Imm));
1072 }
1073
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001074 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001075 void addSImmOperands(MCInst &Inst, unsigned N) const {
1076 if (isImm() && !isConstantImm()) {
1077 addExpr(Inst, getImm());
1078 return;
1079 }
1080 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1081 }
1082
1083 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001084 void addUImmOperands(MCInst &Inst, unsigned N) const {
1085 if (isImm() && !isConstantImm()) {
1086 addExpr(Inst, getImm());
1087 return;
1088 }
1089 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1090 }
1091
Daniel Sanders78e89022016-03-11 11:37:50 +00001092 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1093 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1094 assert(N == 1 && "Invalid number of operands!");
1095 int64_t Imm = getConstantImm() - Offset;
1096 Imm = SignExtend64<Bits>(Imm);
1097 Imm += Offset;
1098 Imm += AdjustOffset;
1099 Inst.addOperand(MCOperand::createImm(Imm));
1100 }
1101
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001102 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001103 assert(N == 1 && "Invalid number of operands!");
1104 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001105 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001106 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001107
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001108 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001109 assert(N == 2 && "Invalid number of operands!");
1110
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001111 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1112 ? getMemBase()->getGPR64Reg()
1113 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001114
1115 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001116 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001117 }
1118
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001119 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1120 assert(N == 2 && "Invalid number of operands!");
1121
Jim Grosbache9119e42015-05-13 18:37:00 +00001122 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001123
1124 const MCExpr *Expr = getMemOff();
1125 addExpr(Inst, Expr);
1126 }
1127
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001128 void addRegListOperands(MCInst &Inst, unsigned N) const {
1129 assert(N == 1 && "Invalid number of operands!");
1130
1131 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001132 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001133 }
1134
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001135 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1136 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001137 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001138 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001139 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1140 Inst.addOperand(MCOperand::createReg(
1141 RegIdx.RegInfo->getRegClass(
1142 AsmParser.getABI().AreGprs64bit()
1143 ? Mips::GPR64RegClassID
1144 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1145 Inst.addOperand(MCOperand::createReg(
1146 RegIdx.RegInfo->getRegClass(
1147 AsmParser.getABI().AreGprs64bit()
1148 ? Mips::GPR64RegClassID
1149 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001150 }
1151
Zoran Jovanovic41688672015-02-10 16:36:20 +00001152 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1153 assert(N == 2 && "Invalid number of operands!");
1154 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001155 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001156 }
1157
Craig Topper56c590a2014-04-29 07:58:02 +00001158 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001159 // As a special case until we sort out the definition of div/divu, accept
1160 // $0/$zero here so that MCK_ZERO works correctly.
1161 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001162 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001163
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001164 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001165 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001166
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001167 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001168 int64_t Res;
1169 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001170 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001171
Daniel Sanders52da7af2015-11-06 12:11:03 +00001172 bool isConstantImmz() const {
1173 return isConstantImm() && getConstantImm() == 0;
1174 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001175
Daniel Sandersea4f6532015-11-06 12:22:31 +00001176 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1177 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1178 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001179
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001180 template <unsigned Bits> bool isSImm() const {
1181 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1182 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001183
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001184 template <unsigned Bits> bool isUImm() const {
1185 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1186 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001187
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001188 template <unsigned Bits> bool isAnyImm() const {
1189 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1190 isUInt<Bits>(getConstantImm()))
1191 : isImm();
1192 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001193
Daniel Sanders78e89022016-03-11 11:37:50 +00001194 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1195 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001196 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001197
Hrvoje Varga46458d02016-02-25 12:53:29 +00001198 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1199 return isConstantImm() && getConstantImm() >= Bottom &&
1200 getConstantImm() <= Top;
1201 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001202
Craig Topper56c590a2014-04-29 07:58:02 +00001203 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001204 // Note: It's not possible to pretend that other operand kinds are tokens.
1205 // The matcher emitter checks tokens first.
1206 return Kind == k_Token;
1207 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001208
Craig Topper56c590a2014-04-29 07:58:02 +00001209 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001210
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001211 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001212 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001213 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001214
Simon Dardis4ccda502016-05-27 13:56:36 +00001215 // Allow relocation operators.
1216 // FIXME: This predicate and others need to look through binary expressions
1217 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001218 template <unsigned Bits, unsigned ShiftAmount = 0>
1219 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001220 if (!isMem())
1221 return false;
1222 if (!getMemBase()->isGPRAsmReg())
1223 return false;
1224 if (isa<MCTargetExpr>(getMemOff()) ||
1225 (isConstantMemOff() &&
1226 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1227 return true;
1228 MCValue Res;
1229 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1230 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001231 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001232
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001233 bool isMemWithGRPMM16Base() const {
1234 return isMem() && getMemBase()->isMM16AsmReg();
1235 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001236
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001237 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1238 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1239 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1240 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001241
Jozef Kolek12c69822014-12-23 16:16:33 +00001242 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1243 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1244 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1245 && (getMemBase()->getGPR32Reg() == Mips::SP);
1246 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001247
Daniel Sanderse473dc92016-05-09 13:38:25 +00001248 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1249 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1250 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1251 && (getMemBase()->getGPR32Reg() == Mips::GP);
1252 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001253
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001254 template <unsigned Bits, unsigned ShiftLeftAmount>
1255 bool isScaledUImm() const {
1256 return isConstantImm() &&
1257 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001258 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001259
Daniel Sanders97297772016-03-22 14:40:00 +00001260 template <unsigned Bits, unsigned ShiftLeftAmount>
1261 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001262 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1263 return true;
1264 // Operand can also be a symbol or symbol plus offset in case of relocations.
1265 if (Kind != k_Immediate)
1266 return false;
1267 MCValue Res;
1268 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1269 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001270 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001271
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001272 bool isRegList16() const {
1273 if (!isRegList())
1274 return false;
1275
1276 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001277 if (Size < 2 || Size > 5)
1278 return false;
1279
1280 unsigned R0 = RegList.List->front();
1281 unsigned R1 = RegList.List->back();
1282 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1283 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001284 return false;
1285
1286 int PrevReg = *RegList.List->begin();
1287 for (int i = 1; i < Size - 1; i++) {
1288 int Reg = (*(RegList.List))[i];
1289 if ( Reg != PrevReg + 1)
1290 return false;
1291 PrevReg = Reg;
1292 }
1293
1294 return true;
1295 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001296
Vladimir Medic2b953d02013-10-01 09:48:56 +00001297 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001298
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001299 bool isLSAImm() const {
1300 if (!isConstantImm())
1301 return false;
1302 int64_t Val = getConstantImm();
1303 return 1 <= Val && Val <= 4;
1304 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001305
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001306 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001307
Zoran Jovanovic41688672015-02-10 16:36:20 +00001308 bool isMovePRegPair() const {
1309 if (Kind != k_RegList || RegList.List->size() != 2)
1310 return false;
1311
1312 unsigned R0 = RegList.List->front();
1313 unsigned R1 = RegList.List->back();
1314
1315 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1316 (R0 == Mips::A1 && R1 == Mips::A3) ||
1317 (R0 == Mips::A2 && R1 == Mips::A3) ||
1318 (R0 == Mips::A0 && R1 == Mips::S5) ||
1319 (R0 == Mips::A0 && R1 == Mips::S6) ||
1320 (R0 == Mips::A0 && R1 == Mips::A1) ||
1321 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001322 (R0 == Mips::A0 && R1 == Mips::A3) ||
1323 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1324 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1325 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1326 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1327 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1328 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1329 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1330 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001331 return true;
1332
1333 return false;
1334 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001335
1336 StringRef getToken() const {
1337 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001338 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001339 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001340
Zlatko Buljanba553a62016-05-09 08:07:28 +00001341 bool isRegPair() const {
1342 return Kind == k_RegPair && RegIdx.Index <= 30;
1343 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001344
Craig Topper56c590a2014-04-29 07:58:02 +00001345 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001346 // As a special case until we sort out the definition of div/divu, accept
1347 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001348 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1349 RegIdx.Kind & RegKind_GPR)
1350 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001351
Daniel Sanders976d9382016-07-05 13:38:40 +00001352 llvm_unreachable("Invalid access!");
1353 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001354 }
1355
Jack Carterb4dbc172012-09-05 23:34:03 +00001356 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001357 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001358 return Imm.Val;
1359 }
1360
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001361 int64_t getConstantImm() const {
1362 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001363 int64_t Value = 0;
1364 (void)Val->evaluateAsAbsolute(Value);
1365 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001366 }
1367
1368 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001369 assert((Kind == k_Memory) && "Invalid access!");
1370 return Mem.Base;
1371 }
1372
1373 const MCExpr *getMemOff() const {
1374 assert((Kind == k_Memory) && "Invalid access!");
1375 return Mem.Off;
1376 }
1377
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001378 int64_t getConstantMemOff() const {
1379 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1380 }
1381
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001382 const SmallVectorImpl<unsigned> &getRegList() const {
1383 assert((Kind == k_RegList) && "Invalid access!");
1384 return *(RegList.List);
1385 }
1386
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001387 unsigned getRegPair() const {
1388 assert((Kind == k_RegPair) && "Invalid access!");
1389 return RegIdx.Index;
1390 }
1391
David Blaikie960ea3f2014-06-08 16:18:35 +00001392 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1393 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001394 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001395 Op->Tok.Data = Str.data();
1396 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001397 Op->StartLoc = S;
1398 Op->EndLoc = S;
1399 return Op;
1400 }
1401
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001402 /// Create a numeric register (e.g. $1). The exact register remains
1403 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001404 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001405 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1406 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001407 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001408 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001409 }
1410
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001411 /// Create a register that is definitely a GPR.
1412 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001413 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001414 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1415 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1416 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001417 }
1418
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001419 /// Create a register that is definitely a FGR.
1420 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001421 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001422 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1423 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1424 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001425 }
1426
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001427 /// Create a register that is definitely a HWReg.
1428 /// This is typically only used for named registers such as $hwr_cpunum.
1429 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001430 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001431 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001432 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001433 }
1434
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001435 /// Create a register that is definitely an FCC.
1436 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001437 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001438 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1439 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1440 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001441 }
1442
1443 /// Create a register that is definitely an ACC.
1444 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001445 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001446 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1447 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1448 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001449 }
1450
1451 /// Create a register that is definitely an MSA128.
1452 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001453 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001454 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1455 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1456 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001457 }
1458
1459 /// Create a register that is definitely an MSACtrl.
1460 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001461 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001462 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1463 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1464 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001465 }
1466
David Blaikie960ea3f2014-06-08 16:18:35 +00001467 static std::unique_ptr<MipsOperand>
1468 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001469 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001470 Op->Imm.Val = Val;
1471 Op->StartLoc = S;
1472 Op->EndLoc = E;
1473 return Op;
1474 }
1475
David Blaikie960ea3f2014-06-08 16:18:35 +00001476 static std::unique_ptr<MipsOperand>
1477 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1478 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001479 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001480 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001481 Op->Mem.Off = Off;
1482 Op->StartLoc = S;
1483 Op->EndLoc = E;
1484 return Op;
1485 }
1486
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001487 static std::unique_ptr<MipsOperand>
1488 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1489 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001490 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001491
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001492 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001493 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001494 Op->StartLoc = StartLoc;
1495 Op->EndLoc = EndLoc;
1496 return Op;
1497 }
1498
Daniel Sandersd044e492016-05-09 13:10:57 +00001499 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1500 SMLoc S, SMLoc E,
1501 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001502 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001503 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001504 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1505 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001506 Op->StartLoc = S;
1507 Op->EndLoc = E;
1508 return Op;
1509 }
1510
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001511 bool isGPRAsmReg() const {
1512 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001513 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001514
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001515 bool isMM16AsmReg() const {
1516 if (!(isRegIdx() && RegIdx.Kind))
1517 return false;
1518 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1519 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001520
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001521 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001522 bool isMM16AsmRegZero() const {
1523 if (!(isRegIdx() && RegIdx.Kind))
1524 return false;
1525 return (RegIdx.Index == 0 ||
1526 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1527 RegIdx.Index == 17);
1528 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001529
Zoran Jovanovic41688672015-02-10 16:36:20 +00001530 bool isMM16AsmRegMoveP() const {
1531 if (!(isRegIdx() && RegIdx.Kind))
1532 return false;
1533 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1534 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1535 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001536
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001537 bool isFGRAsmReg() const {
1538 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1539 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001540 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001541
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001542 bool isHWRegsAsmReg() const {
1543 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && 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 isCCRAsmReg() const {
1547 return isRegIdx() && RegIdx.Kind & RegKind_CCR && 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 isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001551 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1552 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001553 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001554 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001555
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001556 bool isACCAsmReg() const {
1557 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001558 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001559
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001560 bool isCOP0AsmReg() const {
1561 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1562 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001563
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001564 bool isCOP2AsmReg() const {
1565 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001566 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001567
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001568 bool isCOP3AsmReg() const {
1569 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1570 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001571
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001572 bool isMSA128AsmReg() const {
1573 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001574 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001575
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001576 bool isMSACtrlAsmReg() const {
1577 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001578 }
1579
Jack Carterb4dbc172012-09-05 23:34:03 +00001580 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001581 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001582 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001583 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001584
Craig Topper56c590a2014-04-29 07:58:02 +00001585 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001586 switch (Kind) {
1587 case k_Immediate:
1588 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001589 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001590 OS << ">";
1591 break;
1592 case k_Memory:
1593 OS << "Mem<";
1594 Mem.Base->print(OS);
1595 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001596 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001597 OS << ">";
1598 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001599 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001600 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1601 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001602 break;
1603 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001604 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001605 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001606 case k_RegList:
1607 OS << "RegList< ";
1608 for (auto Reg : (*RegList.List))
1609 OS << Reg << " ";
1610 OS << ">";
1611 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001612 case k_RegPair:
1613 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1614 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001615 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001616 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001617
1618 bool isValidForTie(const MipsOperand &Other) const {
1619 if (Kind != Other.Kind)
1620 return false;
1621
1622 switch (Kind) {
1623 default:
1624 llvm_unreachable("Unexpected kind");
1625 return false;
1626 case k_RegisterIndex: {
1627 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1628 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1629 return Token == OtherToken;
1630 }
1631 }
1632 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001633}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001634
1635} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001636
Jack Carter9e65aa32013-03-22 00:05:30 +00001637namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001638
Jack Carter9e65aa32013-03-22 00:05:30 +00001639extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001640
1641} // end namespace llvm
1642
Jack Carter9e65aa32013-03-22 00:05:30 +00001643static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1644 return MipsInsts[Opcode];
1645}
1646
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001647static bool hasShortDelaySlot(unsigned Opcode) {
1648 switch (Opcode) {
1649 case Mips::JALS_MM:
1650 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001651 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001652 case Mips::BGEZALS_MM:
1653 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001654 return true;
1655 default:
1656 return false;
1657 }
1658}
1659
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001660static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1661 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1662 return &SRExpr->getSymbol();
1663 }
1664
1665 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1666 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1667 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1668
1669 if (LHSSym)
1670 return LHSSym;
1671
1672 if (RHSSym)
1673 return RHSSym;
1674
1675 return nullptr;
1676 }
1677
1678 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1679 return getSingleMCSymbol(UExpr->getSubExpr());
1680
1681 return nullptr;
1682}
1683
1684static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1685 if (isa<MCSymbolRefExpr>(Expr))
1686 return 1;
1687
1688 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1689 return countMCSymbolRefExpr(BExpr->getLHS()) +
1690 countMCSymbolRefExpr(BExpr->getRHS());
1691
1692 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1693 return countMCSymbolRefExpr(UExpr->getSubExpr());
1694
1695 return 0;
1696}
1697
Jack Carter9e65aa32013-03-22 00:05:30 +00001698bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001699 MCStreamer &Out,
1700 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001701 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001702 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001703 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001704
Jack Carter9e65aa32013-03-22 00:05:30 +00001705 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001706
1707 if (MCID.isBranch() || MCID.isCall()) {
1708 const unsigned Opcode = Inst.getOpcode();
1709 MCOperand Offset;
1710
1711 switch (Opcode) {
1712 default:
1713 break;
Kai Nackee0245392015-01-27 19:11:28 +00001714 case Mips::BBIT0:
1715 case Mips::BBIT032:
1716 case Mips::BBIT1:
1717 case Mips::BBIT132:
1718 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001719 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001720
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001721 case Mips::BEQ:
1722 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001723 case Mips::BEQ_MM:
1724 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001725 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001726 Offset = Inst.getOperand(2);
1727 if (!Offset.isImm())
1728 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001729 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001730 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001731 if (OffsetToAlignment(Offset.getImm(),
1732 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001733 return Error(IDLoc, "branch to misaligned address");
1734 break;
1735 case Mips::BGEZ:
1736 case Mips::BGTZ:
1737 case Mips::BLEZ:
1738 case Mips::BLTZ:
1739 case Mips::BGEZAL:
1740 case Mips::BLTZAL:
1741 case Mips::BC1F:
1742 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001743 case Mips::BGEZ_MM:
1744 case Mips::BGTZ_MM:
1745 case Mips::BLEZ_MM:
1746 case Mips::BLTZ_MM:
1747 case Mips::BGEZAL_MM:
1748 case Mips::BLTZAL_MM:
1749 case Mips::BC1F_MM:
1750 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001751 case Mips::BC1EQZC_MMR6:
1752 case Mips::BC1NEZC_MMR6:
1753 case Mips::BC2EQZC_MMR6:
1754 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001755 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001756 Offset = Inst.getOperand(1);
1757 if (!Offset.isImm())
1758 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001759 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001760 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001761 if (OffsetToAlignment(Offset.getImm(),
1762 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001763 return Error(IDLoc, "branch to misaligned address");
1764 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001765 case Mips::BGEC: case Mips::BGEC_MMR6:
1766 case Mips::BLTC: case Mips::BLTC_MMR6:
1767 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1768 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1769 case Mips::BEQC: case Mips::BEQC_MMR6:
1770 case Mips::BNEC: case Mips::BNEC_MMR6:
1771 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1772 Offset = Inst.getOperand(2);
1773 if (!Offset.isImm())
1774 break; // We'll deal with this situation later on when applying fixups.
1775 if (!isIntN(18, Offset.getImm()))
1776 return Error(IDLoc, "branch target out of range");
1777 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1778 return Error(IDLoc, "branch to misaligned address");
1779 break;
1780 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1781 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1782 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1783 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1784 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1785 Offset = Inst.getOperand(1);
1786 if (!Offset.isImm())
1787 break; // We'll deal with this situation later on when applying fixups.
1788 if (!isIntN(18, Offset.getImm()))
1789 return Error(IDLoc, "branch target out of range");
1790 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1791 return Error(IDLoc, "branch to misaligned address");
1792 break;
1793 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1794 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1795 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1796 Offset = Inst.getOperand(1);
1797 if (!Offset.isImm())
1798 break; // We'll deal with this situation later on when applying fixups.
1799 if (!isIntN(23, Offset.getImm()))
1800 return Error(IDLoc, "branch target out of range");
1801 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1802 return Error(IDLoc, "branch to misaligned address");
1803 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001804 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001805 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001806 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001807 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001808 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1809 Offset = Inst.getOperand(1);
1810 if (!Offset.isImm())
1811 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001812 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001813 return Error(IDLoc, "branch target out of range");
1814 if (OffsetToAlignment(Offset.getImm(), 2LL))
1815 return Error(IDLoc, "branch to misaligned address");
1816 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001817 }
1818 }
1819
Daniel Sandersa84989a2014-06-16 13:25:35 +00001820 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1821 // We still accept it but it is a normal nop.
1822 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1823 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1824 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1825 "nop instruction");
1826 }
1827
Kai Nackee0245392015-01-27 19:11:28 +00001828 if (hasCnMips()) {
1829 const unsigned Opcode = Inst.getOpcode();
1830 MCOperand Opnd;
1831 int Imm;
1832
1833 switch (Opcode) {
1834 default:
1835 break;
1836
1837 case Mips::BBIT0:
1838 case Mips::BBIT032:
1839 case Mips::BBIT1:
1840 case Mips::BBIT132:
1841 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1842 // The offset is handled above
1843 Opnd = Inst.getOperand(1);
1844 if (!Opnd.isImm())
1845 return Error(IDLoc, "expected immediate operand kind");
1846 Imm = Opnd.getImm();
1847 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1848 Opcode == Mips::BBIT1 ? 63 : 31))
1849 return Error(IDLoc, "immediate operand value out of range");
1850 if (Imm > 31) {
1851 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1852 : Mips::BBIT132);
1853 Inst.getOperand(1).setImm(Imm - 32);
1854 }
1855 break;
1856
Kai Nackee0245392015-01-27 19:11:28 +00001857 case Mips::SEQi:
1858 case Mips::SNEi:
1859 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1860 Opnd = Inst.getOperand(2);
1861 if (!Opnd.isImm())
1862 return Error(IDLoc, "expected immediate operand kind");
1863 Imm = Opnd.getImm();
1864 if (!isInt<10>(Imm))
1865 return Error(IDLoc, "immediate operand value out of range");
1866 break;
1867 }
1868 }
1869
Simon Atanasyan50485142016-12-12 17:40:26 +00001870 // For PIC code convert unconditional jump to unconditional branch.
1871 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
1872 inPicMode()) {
1873 MCInst BInst;
1874 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
1875 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1876 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1877 BInst.addOperand(Inst.getOperand(0));
1878 Inst = BInst;
1879 }
1880
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001881 // This expansion is not in a function called by tryExpandInstruction()
1882 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001883 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1884 inPicMode()) {
1885 warnIfNoMacro(IDLoc);
1886
1887 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1888
1889 // We can do this expansion if there's only 1 symbol in the argument
1890 // expression.
1891 if (countMCSymbolRefExpr(JalExpr) > 1)
1892 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1893
1894 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001895 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001896 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1897
1898 // FIXME: Add support for label+offset operands (currently causes an error).
1899 // FIXME: Add support for forward-declared local symbols.
1900 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00001901 if (JalSym->isInSection() || JalSym->isTemporary() ||
1902 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001903 if (isABI_O32()) {
1904 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001905 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001906 // R_(MICRO)MIPS_GOT16 label
1907 // addiu $25, $25, 0
1908 // R_(MICRO)MIPS_LO16 label
1909 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001910 const MCExpr *Got16RelocExpr =
1911 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1912 const MCExpr *Lo16RelocExpr =
1913 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001914
Daniel Sandersa736b372016-04-29 13:33:12 +00001915 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1916 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1917 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1918 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001919 } else if (isABI_N32() || isABI_N64()) {
1920 // If it's a local symbol and the N32/N64 ABIs are being used,
1921 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001922 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001923 // R_(MICRO)MIPS_GOT_DISP label
1924 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001925 const MCExpr *GotDispRelocExpr =
1926 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001927
Daniel Sandersa736b372016-04-29 13:33:12 +00001928 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1929 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1930 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001931 }
1932 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001933 // If it's an external/weak symbol, we expand to:
1934 // lw/ld $25, 0($gp)
1935 // R_(MICRO)MIPS_CALL16 label
1936 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001937 const MCExpr *Call16RelocExpr =
1938 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001939
Daniel Sandersa736b372016-04-29 13:33:12 +00001940 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1941 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001942 }
1943
1944 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001945 if (IsCpRestoreSet && inMicroMipsMode())
1946 JalrInst.setOpcode(Mips::JALRS_MM);
1947 else
1948 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001949 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1950 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1951
1952 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1953 // This relocation is supposed to be an optimization hint for the linker
1954 // and is not necessary for correctness.
1955
1956 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001957 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001958 }
1959
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001960 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
1961 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001962 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001963 // reference or immediate we may have to expand instructions.
1964 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001965 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001966 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1967 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001968 MCOperand &Op = Inst.getOperand(i);
1969 if (Op.isImm()) {
1970 int MemOffset = Op.getImm();
1971 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001972 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001973 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00001974 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001975 }
1976 } else if (Op.isExpr()) {
1977 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001978 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001979 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001980 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001981 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001982 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001983 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00001984 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001985 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001986 } else if (!isEvaluated(Expr)) {
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 }
1990 }
1991 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001992 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001993 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001994
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001995 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001996 if (MCID.mayLoad()) {
1997 // Try to create 16-bit GP relative load instruction.
1998 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1999 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2000 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2001 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2002 MCOperand &Op = Inst.getOperand(i);
2003 if (Op.isImm()) {
2004 int MemOffset = Op.getImm();
2005 MCOperand &DstReg = Inst.getOperand(0);
2006 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002007 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002008 getContext().getRegisterInfo()->getRegClass(
2009 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002010 (BaseReg.getReg() == Mips::GP ||
2011 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002012
Daniel Sandersa736b372016-04-29 13:33:12 +00002013 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2014 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002015 return false;
2016 }
2017 }
2018 }
2019 } // for
2020 } // if load
2021
2022 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2023
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002024 MCOperand Opnd;
2025 int Imm;
2026
2027 switch (Inst.getOpcode()) {
2028 default:
2029 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002030 case Mips::ADDIUSP_MM:
2031 Opnd = Inst.getOperand(0);
2032 if (!Opnd.isImm())
2033 return Error(IDLoc, "expected immediate operand kind");
2034 Imm = Opnd.getImm();
2035 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2036 Imm % 4 != 0)
2037 return Error(IDLoc, "immediate operand value out of range");
2038 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002039 case Mips::SLL16_MM:
2040 case Mips::SRL16_MM:
2041 Opnd = Inst.getOperand(2);
2042 if (!Opnd.isImm())
2043 return Error(IDLoc, "expected immediate operand kind");
2044 Imm = Opnd.getImm();
2045 if (Imm < 1 || Imm > 8)
2046 return Error(IDLoc, "immediate operand value out of range");
2047 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002048 case Mips::LI16_MM:
2049 Opnd = Inst.getOperand(1);
2050 if (!Opnd.isImm())
2051 return Error(IDLoc, "expected immediate operand kind");
2052 Imm = Opnd.getImm();
2053 if (Imm < -1 || Imm > 126)
2054 return Error(IDLoc, "immediate operand value out of range");
2055 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002056 case Mips::ADDIUR2_MM:
2057 Opnd = Inst.getOperand(2);
2058 if (!Opnd.isImm())
2059 return Error(IDLoc, "expected immediate operand kind");
2060 Imm = Opnd.getImm();
2061 if (!(Imm == 1 || Imm == -1 ||
2062 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2063 return Error(IDLoc, "immediate operand value out of range");
2064 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002065 case Mips::ANDI16_MM:
2066 Opnd = Inst.getOperand(2);
2067 if (!Opnd.isImm())
2068 return Error(IDLoc, "expected immediate operand kind");
2069 Imm = Opnd.getImm();
2070 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2071 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2072 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2073 return Error(IDLoc, "immediate operand value out of range");
2074 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002075 case Mips::LBU16_MM:
2076 Opnd = Inst.getOperand(2);
2077 if (!Opnd.isImm())
2078 return Error(IDLoc, "expected immediate operand kind");
2079 Imm = Opnd.getImm();
2080 if (Imm < -1 || Imm > 14)
2081 return Error(IDLoc, "immediate operand value out of range");
2082 break;
2083 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002084 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002085 Opnd = Inst.getOperand(2);
2086 if (!Opnd.isImm())
2087 return Error(IDLoc, "expected immediate operand kind");
2088 Imm = Opnd.getImm();
2089 if (Imm < 0 || Imm > 15)
2090 return Error(IDLoc, "immediate operand value out of range");
2091 break;
2092 case Mips::LHU16_MM:
2093 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002094 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002095 Opnd = Inst.getOperand(2);
2096 if (!Opnd.isImm())
2097 return Error(IDLoc, "expected immediate operand kind");
2098 Imm = Opnd.getImm();
2099 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2100 return Error(IDLoc, "immediate operand value out of range");
2101 break;
2102 case Mips::LW16_MM:
2103 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002104 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002105 Opnd = Inst.getOperand(2);
2106 if (!Opnd.isImm())
2107 return Error(IDLoc, "expected immediate operand kind");
2108 Imm = Opnd.getImm();
2109 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2110 return Error(IDLoc, "immediate operand value out of range");
2111 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002112 case Mips::ADDIUPC_MM:
2113 MCOperand Opnd = Inst.getOperand(1);
2114 if (!Opnd.isImm())
2115 return Error(IDLoc, "expected immediate operand kind");
2116 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002117 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002118 return Error(IDLoc, "immediate operand value out of range");
2119 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002120 }
2121 }
2122
Daniel Sandersd8c07762016-04-18 12:35:36 +00002123 bool FillDelaySlot =
2124 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2125 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002126 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002127
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002128 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002129 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002130 switch (ExpandResult) {
2131 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002132 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002133 break;
2134 case MER_Success:
2135 break;
2136 case MER_Fail:
2137 return true;
2138 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002139
Daniel Sanderscda908a2016-05-16 09:10:13 +00002140 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2141 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2142 if (inMicroMipsMode())
2143 TOut.setUsesMicroMips();
2144
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002145 // If this instruction has a delay slot and .set reorder is active,
2146 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002147 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002148 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2149 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002150 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002151
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002152 if ((Inst.getOpcode() == Mips::JalOneReg ||
2153 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2154 isPicAndNotNxxAbi()) {
2155 if (IsCpRestoreSet) {
2156 // We need a NOP between the JALR and the LW:
2157 // If .set reorder has been used, we've already emitted a NOP.
2158 // If .set noreorder has been used, we need to emit a NOP at this point.
2159 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002160 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2161 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002162
2163 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002164 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002165 } else
2166 Warning(IDLoc, "no .cprestore used in PIC mode");
2167 }
2168
Jack Carter9e65aa32013-03-22 00:05:30 +00002169 return false;
2170}
2171
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002172MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002173MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2174 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002175 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002176 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002177 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002178 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002179 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002180 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002181 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002182 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002183 case Mips::LoadAddrImm64:
2184 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2185 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2186 "expected immediate operand kind");
2187
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002188 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2189 Inst.getOperand(1),
2190 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002191 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002192 ? MER_Fail
2193 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002194 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002195 case Mips::LoadAddrReg64:
2196 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2197 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2198 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2199 "expected immediate operand kind");
2200
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002201 return expandLoadAddress(Inst.getOperand(0).getReg(),
2202 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2203 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002204 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002205 ? MER_Fail
2206 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002207 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002208 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002209 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2210 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002211 case Mips::SWM_MM:
2212 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002213 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2214 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002215 case Mips::JalOneReg:
2216 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002217 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002218 case Mips::BneImm:
2219 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002220 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002221 case Mips::BLT:
2222 case Mips::BLE:
2223 case Mips::BGE:
2224 case Mips::BGT:
2225 case Mips::BLTU:
2226 case Mips::BLEU:
2227 case Mips::BGEU:
2228 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002229 case Mips::BLTL:
2230 case Mips::BLEL:
2231 case Mips::BGEL:
2232 case Mips::BGTL:
2233 case Mips::BLTUL:
2234 case Mips::BLEUL:
2235 case Mips::BGEUL:
2236 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002237 case Mips::BLTImmMacro:
2238 case Mips::BLEImmMacro:
2239 case Mips::BGEImmMacro:
2240 case Mips::BGTImmMacro:
2241 case Mips::BLTUImmMacro:
2242 case Mips::BLEUImmMacro:
2243 case Mips::BGEUImmMacro:
2244 case Mips::BGTUImmMacro:
2245 case Mips::BLTLImmMacro:
2246 case Mips::BLELImmMacro:
2247 case Mips::BGELImmMacro:
2248 case Mips::BGTLImmMacro:
2249 case Mips::BLTULImmMacro:
2250 case Mips::BLEULImmMacro:
2251 case Mips::BGEULImmMacro:
2252 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002253 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002254 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002255 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002256 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2257 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002258 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002259 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002260 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2261 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002262 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002263 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002264 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2265 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002266 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002267 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002268 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2269 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002270 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002271 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2272 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002273 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002274 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002275 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002276 case Mips::PseudoTRUNC_W_D:
2277 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2278 : MER_Success;
2279 case Mips::Ulh:
2280 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2281 case Mips::Ulhu:
2282 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002283 case Mips::Ush:
2284 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002285 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002286 case Mips::Usw:
2287 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002288 case Mips::NORImm:
2289 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002290 case Mips::ADDi:
2291 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002292 case Mips::SLTi:
2293 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002294 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2295 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2296 int64_t ImmValue = Inst.getOperand(2).getImm();
2297 if (isInt<16>(ImmValue))
2298 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002299 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2300 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002301 }
2302 return MER_NotAMacro;
2303 case Mips::ANDi:
2304 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002305 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002306 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2307 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2308 int64_t ImmValue = Inst.getOperand(2).getImm();
2309 if (isUInt<16>(ImmValue))
2310 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002311 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2312 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002313 }
2314 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002315 case Mips::ROL:
2316 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002317 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002318 case Mips::ROLImm:
2319 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002320 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002321 case Mips::DROL:
2322 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002323 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002324 case Mips::DROLImm:
2325 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002326 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002327 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002328 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002329 case Mips::LDMacro:
2330 case Mips::SDMacro:
2331 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2332 Inst.getOpcode() == Mips::LDMacro)
2333 ? MER_Fail
2334 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002335 case Mips::SEQMacro:
2336 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2337 case Mips::SEQIMacro:
2338 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002339 }
Jack Carter30a59822012-10-04 04:03:53 +00002340}
Jack Carter92995f12012-10-06 00:53:28 +00002341
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002342bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002343 MCStreamer &Out,
2344 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002345 MipsTargetStreamer &TOut = getTargetStreamer();
2346
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002347 // Create a JALR instruction which is going to replace the pseudo-JAL.
2348 MCInst JalrInst;
2349 JalrInst.setLoc(IDLoc);
2350 const MCOperand FirstRegOp = Inst.getOperand(0);
2351 const unsigned Opcode = Inst.getOpcode();
2352
2353 if (Opcode == Mips::JalOneReg) {
2354 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002355 if (IsCpRestoreSet && inMicroMipsMode()) {
2356 JalrInst.setOpcode(Mips::JALRS16_MM);
2357 JalrInst.addOperand(FirstRegOp);
2358 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002359 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002360 JalrInst.addOperand(FirstRegOp);
2361 } else {
2362 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002363 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002364 JalrInst.addOperand(FirstRegOp);
2365 }
2366 } else if (Opcode == Mips::JalTwoReg) {
2367 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002368 if (IsCpRestoreSet && inMicroMipsMode())
2369 JalrInst.setOpcode(Mips::JALRS_MM);
2370 else
2371 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002372 JalrInst.addOperand(FirstRegOp);
2373 const MCOperand SecondRegOp = Inst.getOperand(1);
2374 JalrInst.addOperand(SecondRegOp);
2375 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002376 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002377
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002378 // If .set reorder is active and branch instruction has a delay slot,
2379 // emit a NOP after it.
2380 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002381 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2382 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2383 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002384
2385 return false;
2386}
2387
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002388/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002389template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002390 unsigned BitNum = findFirstSet(x);
2391
2392 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2393}
2394
2395/// Load (or add) an immediate into a register.
2396///
2397/// @param ImmValue The immediate to load.
2398/// @param DstReg The register that will hold the immediate.
2399/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2400/// for a simple initialization.
2401/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2402/// @param IsAddress True if the immediate represents an address. False if it
2403/// is an integer.
2404/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002405bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002406 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002407 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2408 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002409 MipsTargetStreamer &TOut = getTargetStreamer();
2410
Toma Tabacu00e98672015-05-01 12:19:27 +00002411 if (!Is32BitImm && !isGP64bit()) {
2412 Error(IDLoc, "instruction requires a 64-bit architecture");
2413 return true;
2414 }
2415
Daniel Sanders03f9c012015-07-14 12:24:22 +00002416 if (Is32BitImm) {
2417 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2418 // Sign extend up to 64-bit so that the predicates match the hardware
2419 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2420 // true.
2421 ImmValue = SignExtend64<32>(ImmValue);
2422 } else {
2423 Error(IDLoc, "instruction requires a 32-bit immediate");
2424 return true;
2425 }
2426 }
2427
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002428 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2429 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2430
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002431 bool UseSrcReg = false;
2432 if (SrcReg != Mips::NoRegister)
2433 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002434
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002435 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002436 if (UseSrcReg &&
2437 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002438 // At this point we need AT to perform the expansions and we exit if it is
2439 // not available.
2440 unsigned ATReg = getATReg(IDLoc);
2441 if (!ATReg)
2442 return true;
2443 TmpReg = ATReg;
2444 }
2445
Daniel Sanders03f9c012015-07-14 12:24:22 +00002446 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002447 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002448 SrcReg = ZeroReg;
2449
2450 // This doesn't quite follow the usual ABI expectations for N32 but matches
2451 // traditional assembler behaviour. N32 would normally use addiu for both
2452 // integers and addresses.
2453 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002454 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002455 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002456 }
2457
Daniel Sandersa736b372016-04-29 13:33:12 +00002458 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002459 return false;
2460 }
2461
2462 if (isUInt<16>(ImmValue)) {
2463 unsigned TmpReg = DstReg;
2464 if (SrcReg == DstReg) {
2465 TmpReg = getATReg(IDLoc);
2466 if (!TmpReg)
2467 return true;
2468 }
2469
Daniel Sandersa736b372016-04-29 13:33:12 +00002470 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002471 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002472 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002473 return false;
2474 }
2475
2476 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002477 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002478
Toma Tabacu79588102015-04-29 10:19:56 +00002479 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2480 uint16_t Bits15To0 = ImmValue & 0xffff;
2481
Toma Tabacua3d056f2015-05-15 09:42:11 +00002482 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002483 // Traditional behaviour seems to special case this particular value. It's
2484 // not clear why other masks are handled differently.
2485 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002486 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2487 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002488 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002489 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002490 return false;
2491 }
2492
2493 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002494 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002495 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2496 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002497 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002498 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002499 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002500 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002501 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002502 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002503
Daniel Sandersa736b372016-04-29 13:33:12 +00002504 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002505 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002506 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002507 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002508 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002509 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002510 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002511
2512 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2513 if (Is32BitImm) {
2514 Error(IDLoc, "instruction requires a 32-bit immediate");
2515 return true;
2516 }
2517
2518 // Traditionally, these immediates are shifted as little as possible and as
2519 // such we align the most significant bit to bit 15 of our temporary.
2520 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2521 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2522 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2523 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002524 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2525 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002526
2527 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002528 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002529
2530 return false;
2531 }
2532
2533 warnIfNoMacro(IDLoc);
2534
2535 // The remaining case is packed with a sequence of dsll and ori with zeros
2536 // being omitted and any neighbouring dsll's being coalesced.
2537 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2538
2539 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2540 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002541 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002542 return false;
2543
2544 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2545 // skip it and defer the shift to the next chunk.
2546 unsigned ShiftCarriedForwards = 16;
2547 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2548 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2549
2550 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002551 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2552 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002553 ShiftCarriedForwards = 0;
2554 }
2555
2556 ShiftCarriedForwards += 16;
2557 }
2558 ShiftCarriedForwards -= 16;
2559
2560 // Finish any remaining shifts left by trailing zeros.
2561 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002562 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002563
2564 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002565 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002566
Matheus Almeida3813d572014-06-19 14:39:14 +00002567 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002568}
Jack Carter92995f12012-10-06 00:53:28 +00002569
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002570bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002571 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002572 const MCOperand &ImmOp = Inst.getOperand(1);
2573 assert(ImmOp.isImm() && "expected immediate operand kind");
2574 const MCOperand &DstRegOp = Inst.getOperand(0);
2575 assert(DstRegOp.isReg() && "expected register operand kind");
2576
2577 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002578 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002579 return true;
2580
2581 return false;
2582}
2583
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002584bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2585 const MCOperand &Offset,
2586 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002587 MCStreamer &Out,
2588 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002589 // la can't produce a usable address when addresses are 64-bit.
2590 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2591 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2592 // We currently can't do this because we depend on the equality
2593 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2594 Error(IDLoc, "la used to load 64-bit address");
2595 // Continue as if we had 'dla' instead.
2596 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002597 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002598 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002599
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002600 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002601 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002602 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +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 if (!Offset.isImm())
2607 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002608 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002609
Scott Egerton24557012016-01-21 15:11:01 +00002610 if (!ABI.ArePtrs64bit()) {
2611 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2612 Is32BitAddress = true;
2613 }
2614
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002615 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002616 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002617}
2618
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002619bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2620 unsigned DstReg, unsigned SrcReg,
2621 bool Is32BitSym, SMLoc IDLoc,
2622 MCStreamer &Out,
2623 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002624 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002625 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002626 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002627
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002628 if (inPicMode() && ABI.IsO32()) {
2629 MCValue Res;
2630 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2631 Error(IDLoc, "expected relocatable expression");
2632 return true;
2633 }
2634 if (Res.getSymB() != nullptr) {
2635 Error(IDLoc, "expected relocatable expression with only one symbol");
2636 return true;
2637 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002638
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002639 // The case where the result register is $25 is somewhat special. If the
2640 // symbol in the final relocation is external and not modified with a
2641 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2642 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2643 Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
2644 !Res.getSymA()->getSymbol().isTemporary()) {
2645 const MCExpr *CallExpr =
2646 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2647 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2648 MCOperand::createExpr(CallExpr), IDLoc, STI);
2649 return false;
2650 }
2651
2652 // The remaining cases are:
2653 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2654 // >addiu $tmp, $tmp, %lo(offset)
2655 // >addiu $rd, $tmp, $rs
2656 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2657 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2658 // >addiu $rd, $tmp, $rs
2659 // The addiu's marked with a '>' may be omitted if they are redundant. If
2660 // this happens then the last instruction must use $rd as the result
2661 // register.
2662 const MipsMCExpr *GotExpr =
2663 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2664 const MCExpr *LoExpr = nullptr;
2665 if (Res.getSymA()->getSymbol().isInSection() ||
2666 Res.getSymA()->getSymbol().isTemporary())
2667 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2668 else if (Res.getConstant() != 0) {
2669 // External symbols fully resolve the symbol with just the %got(symbol)
2670 // but we must still account for any offset to the symbol for expressions
2671 // like symbol+8.
2672 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2673 }
2674
2675 unsigned TmpReg = DstReg;
2676 if (UseSrcReg &&
2677 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2678 SrcReg)) {
2679 // If $rs is the same as $rd, we need to use AT.
2680 // If it is not available we exit.
2681 unsigned ATReg = getATReg(IDLoc);
2682 if (!ATReg)
2683 return true;
2684 TmpReg = ATReg;
2685 }
2686
2687 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2688 MCOperand::createExpr(GotExpr), IDLoc, STI);
2689
2690 if (LoExpr)
2691 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2692 IDLoc, STI);
2693
2694 if (UseSrcReg)
2695 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2696
2697 return false;
2698 }
2699
2700 const MipsMCExpr *HiExpr =
2701 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2702 const MipsMCExpr *LoExpr =
2703 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002704
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002705 // This is the 64-bit symbol address expansion.
2706 if (ABI.ArePtrs64bit() && isGP64bit()) {
2707 // We always need AT for the 64-bit expansion.
2708 // If it is not available we exit.
2709 unsigned ATReg = getATReg(IDLoc);
2710 if (!ATReg)
2711 return true;
2712
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002713 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002714 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002715 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002716 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002717
Scott Egerton24557012016-01-21 15:11:01 +00002718 if (UseSrcReg &&
2719 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2720 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002721 // If $rs is the same as $rd:
2722 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2723 // daddiu $at, $at, %higher(sym)
2724 // dsll $at, $at, 16
2725 // daddiu $at, $at, %hi(sym)
2726 // dsll $at, $at, 16
2727 // daddiu $at, $at, %lo(sym)
2728 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002729 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2730 STI);
2731 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2732 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2733 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2734 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2735 IDLoc, STI);
2736 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2737 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2738 IDLoc, STI);
2739 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002740
2741 return false;
2742 }
2743
2744 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2745 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2746 // lui $at, %hi(sym)
2747 // daddiu $rd, $rd, %higher(sym)
2748 // daddiu $at, $at, %lo(sym)
2749 // dsll32 $rd, $rd, 0
2750 // daddu $rd, $rd, $at
2751 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002752 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2753 STI);
2754 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2755 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2756 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2757 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2758 IDLoc, STI);
2759 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2760 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002761 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002762 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002763
2764 return false;
2765 }
2766
2767 // And now, the 32-bit symbol address expansion:
2768 // If $rs is the same as $rd:
2769 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2770 // ori $at, $at, %lo(sym)
2771 // addu $rd, $at, $rd
2772 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2773 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2774 // ori $rd, $rd, %lo(sym)
2775 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002776 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002777 if (UseSrcReg &&
2778 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002779 // If $rs is the same as $rd, we need to use AT.
2780 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002781 unsigned ATReg = getATReg(IDLoc);
2782 if (!ATReg)
2783 return true;
2784 TmpReg = ATReg;
2785 }
2786
Daniel Sandersa736b372016-04-29 13:33:12 +00002787 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2788 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2789 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002790
Toma Tabacufb9d1252015-06-22 12:08:39 +00002791 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002792 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002793 else
Scott Egerton24557012016-01-21 15:11:01 +00002794 assert(
2795 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002796
Toma Tabacu674825c2015-06-16 12:16:24 +00002797 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002798}
2799
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002800bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2801 MCStreamer &Out,
2802 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002803 MipsTargetStreamer &TOut = getTargetStreamer();
2804
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002805 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2806 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002807
2808 MCOperand Offset = Inst.getOperand(0);
2809 if (Offset.isExpr()) {
2810 Inst.clear();
2811 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002812 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2813 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2814 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002815 } else {
2816 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002817 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002818 // If offset fits into 11 bits then this instruction becomes microMIPS
2819 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002820 if (inMicroMipsMode())
2821 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002822 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002823 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00002824 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002825 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00002826 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002827 Inst.clear();
2828 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002829 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2830 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2831 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002832 }
2833 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002834 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002835
Zoran Jovanovicada70912015-09-07 11:56:37 +00002836 // If .set reorder is active and branch instruction has a delay slot,
2837 // emit a NOP after it.
2838 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2839 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002840 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002841
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002842 return false;
2843}
2844
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002845bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2846 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002847 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002848 const MCOperand &DstRegOp = Inst.getOperand(0);
2849 assert(DstRegOp.isReg() && "expected register operand kind");
2850
2851 const MCOperand &ImmOp = Inst.getOperand(1);
2852 assert(ImmOp.isImm() && "expected immediate operand kind");
2853
2854 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002855 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2856 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002857
2858 unsigned OpCode = 0;
2859 switch(Inst.getOpcode()) {
2860 case Mips::BneImm:
2861 OpCode = Mips::BNE;
2862 break;
2863 case Mips::BeqImm:
2864 OpCode = Mips::BEQ;
2865 break;
2866 default:
2867 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2868 break;
2869 }
2870
2871 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002872 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002873 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2874 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002875 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002876 warnIfNoMacro(IDLoc);
2877
2878 unsigned ATReg = getATReg(IDLoc);
2879 if (!ATReg)
2880 return true;
2881
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002882 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002883 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002884 return true;
2885
Daniel Sandersa736b372016-04-29 13:33:12 +00002886 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002887 }
2888 return false;
2889}
2890
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002891void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002892 const MCSubtargetInfo *STI, bool IsLoad,
2893 bool IsImmOpnd) {
2894 if (IsLoad) {
2895 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2896 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002897 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002898 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2899}
2900
2901void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2902 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2903 MipsTargetStreamer &TOut = getTargetStreamer();
2904
2905 unsigned DstReg = Inst.getOperand(0).getReg();
2906 unsigned BaseReg = Inst.getOperand(1).getReg();
2907
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002908 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002909 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2910 unsigned DstRegClassID =
2911 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2912 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2913 (DstRegClassID == Mips::GPR64RegClassID);
2914
2915 if (IsImmOpnd) {
2916 // Try to use DstReg as the temporary.
2917 if (IsGPR && (BaseReg != DstReg)) {
2918 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2919 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2920 STI);
2921 return;
2922 }
2923
Matheus Almeida7de68e72014-06-18 14:46:05 +00002924 // At this point we need AT to perform the expansions and we exit if it is
2925 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002926 unsigned ATReg = getATReg(IDLoc);
2927 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002928 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002929
2930 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2931 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2932 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002933 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002934
Daniel Sandersfba875f2016-04-29 13:43:45 +00002935 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002936 MCOperand LoOperand = MCOperand::createExpr(
2937 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2938 MCOperand HiOperand = MCOperand::createExpr(
2939 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002940
2941 // Try to use DstReg as the temporary.
2942 if (IsGPR && (BaseReg != DstReg)) {
2943 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2944 LoOperand, DstReg, IDLoc, STI);
2945 return;
2946 }
2947
2948 // At this point we need AT to perform the expansions and we exit if it is
2949 // not available.
2950 unsigned ATReg = getATReg(IDLoc);
2951 if (!ATReg)
2952 return;
2953
2954 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2955 LoOperand, ATReg, IDLoc, STI);
2956}
2957
2958void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2959 const MCSubtargetInfo *STI,
2960 bool IsImmOpnd) {
2961 MipsTargetStreamer &TOut = getTargetStreamer();
2962
2963 unsigned SrcReg = Inst.getOperand(0).getReg();
2964 unsigned BaseReg = Inst.getOperand(1).getReg();
2965
Daniel Sanders241c6792016-05-12 14:01:50 +00002966 if (IsImmOpnd) {
2967 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2968 Inst.getOperand(2).getImm(),
2969 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
2970 return;
2971 }
2972
Daniel Sandersfba875f2016-04-29 13:43:45 +00002973 unsigned ATReg = getATReg(IDLoc);
2974 if (!ATReg)
2975 return;
2976
Daniel Sandersfba875f2016-04-29 13:43:45 +00002977 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002978 MCOperand LoOperand = MCOperand::createExpr(
2979 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2980 MCOperand HiOperand = MCOperand::createExpr(
2981 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002982 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2983 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002984}
2985
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002986bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2987 MCStreamer &Out,
2988 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002989 unsigned OpNum = Inst.getNumOperands();
2990 unsigned Opcode = Inst.getOpcode();
2991 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2992
Eugene Zelenkodde94e42017-01-30 23:21:32 +00002993 assert(Inst.getOperand(OpNum - 1).isImm() &&
2994 Inst.getOperand(OpNum - 2).isReg() &&
2995 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002996
2997 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2998 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002999 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3000 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3001 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3002 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003003 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003004 if (inMicroMipsMode() && hasMips32r6())
3005 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3006 else
3007 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3008 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003009
3010 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003011 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003012 return false;
3013}
3014
Toma Tabacu1a108322015-06-17 13:20:24 +00003015bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003016 MCStreamer &Out,
3017 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003018 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003019 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003020 unsigned PseudoOpcode = Inst.getOpcode();
3021 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003022 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003023 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3024
3025 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003026 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003027
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003028 unsigned TrgReg;
3029 if (TrgOp.isReg())
3030 TrgReg = TrgOp.getReg();
3031 else if (TrgOp.isImm()) {
3032 warnIfNoMacro(IDLoc);
3033 EmittedNoMacroWarning = true;
3034
3035 TrgReg = getATReg(IDLoc);
3036 if (!TrgReg)
3037 return true;
3038
3039 switch(PseudoOpcode) {
3040 default:
3041 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3042 case Mips::BLTImmMacro:
3043 PseudoOpcode = Mips::BLT;
3044 break;
3045 case Mips::BLEImmMacro:
3046 PseudoOpcode = Mips::BLE;
3047 break;
3048 case Mips::BGEImmMacro:
3049 PseudoOpcode = Mips::BGE;
3050 break;
3051 case Mips::BGTImmMacro:
3052 PseudoOpcode = Mips::BGT;
3053 break;
3054 case Mips::BLTUImmMacro:
3055 PseudoOpcode = Mips::BLTU;
3056 break;
3057 case Mips::BLEUImmMacro:
3058 PseudoOpcode = Mips::BLEU;
3059 break;
3060 case Mips::BGEUImmMacro:
3061 PseudoOpcode = Mips::BGEU;
3062 break;
3063 case Mips::BGTUImmMacro:
3064 PseudoOpcode = Mips::BGTU;
3065 break;
3066 case Mips::BLTLImmMacro:
3067 PseudoOpcode = Mips::BLTL;
3068 break;
3069 case Mips::BLELImmMacro:
3070 PseudoOpcode = Mips::BLEL;
3071 break;
3072 case Mips::BGELImmMacro:
3073 PseudoOpcode = Mips::BGEL;
3074 break;
3075 case Mips::BGTLImmMacro:
3076 PseudoOpcode = Mips::BGTL;
3077 break;
3078 case Mips::BLTULImmMacro:
3079 PseudoOpcode = Mips::BLTUL;
3080 break;
3081 case Mips::BLEULImmMacro:
3082 PseudoOpcode = Mips::BLEUL;
3083 break;
3084 case Mips::BGEULImmMacro:
3085 PseudoOpcode = Mips::BGEUL;
3086 break;
3087 case Mips::BGTULImmMacro:
3088 PseudoOpcode = Mips::BGTUL;
3089 break;
3090 }
3091
3092 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003093 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003094 return true;
3095 }
3096
Toma Tabacu1a108322015-06-17 13:20:24 +00003097 switch (PseudoOpcode) {
3098 case Mips::BLT:
3099 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003100 case Mips::BLTL:
3101 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003102 AcceptsEquality = false;
3103 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003104 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3105 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003106 ZeroSrcOpcode = Mips::BGTZ;
3107 ZeroTrgOpcode = Mips::BLTZ;
3108 break;
3109 case Mips::BLE:
3110 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003111 case Mips::BLEL:
3112 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003113 AcceptsEquality = true;
3114 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003115 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3116 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003117 ZeroSrcOpcode = Mips::BGEZ;
3118 ZeroTrgOpcode = Mips::BLEZ;
3119 break;
3120 case Mips::BGE:
3121 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003122 case Mips::BGEL:
3123 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003124 AcceptsEquality = true;
3125 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003126 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3127 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003128 ZeroSrcOpcode = Mips::BLEZ;
3129 ZeroTrgOpcode = Mips::BGEZ;
3130 break;
3131 case Mips::BGT:
3132 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003133 case Mips::BGTL:
3134 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003135 AcceptsEquality = false;
3136 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003137 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3138 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003139 ZeroSrcOpcode = Mips::BLTZ;
3140 ZeroTrgOpcode = Mips::BGTZ;
3141 break;
3142 default:
3143 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3144 }
3145
Toma Tabacu1a108322015-06-17 13:20:24 +00003146 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3147 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3148 if (IsSrcRegZero && IsTrgRegZero) {
3149 // FIXME: All of these Opcode-specific if's are needed for compatibility
3150 // with GAS' behaviour. However, they may not generate the most efficient
3151 // code in some circumstances.
3152 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003153 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3154 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003155 return false;
3156 }
3157 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003158 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3159 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003160 Warning(IDLoc, "branch is always taken");
3161 return false;
3162 }
3163 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003164 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3165 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003166 Warning(IDLoc, "branch is always taken");
3167 return false;
3168 }
3169 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003170 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3171 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003172 return false;
3173 }
3174 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003175 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3176 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003177 return false;
3178 }
3179 if (AcceptsEquality) {
3180 // If both registers are $0 and the pseudo-branch accepts equality, it
3181 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003182 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3183 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003184 Warning(IDLoc, "branch is always taken");
3185 return false;
3186 }
3187 // If both registers are $0 and the pseudo-branch does not accept
3188 // equality, it will never be taken, so we don't have to emit anything.
3189 return false;
3190 }
3191 if (IsSrcRegZero || IsTrgRegZero) {
3192 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3193 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3194 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3195 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3196 // the pseudo-branch will never be taken, so we don't emit anything.
3197 // This only applies to unsigned pseudo-branches.
3198 return false;
3199 }
3200 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3201 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3202 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3203 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3204 // the pseudo-branch will always be taken, so we emit an unconditional
3205 // branch.
3206 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003207 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3208 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003209 Warning(IDLoc, "branch is always taken");
3210 return false;
3211 }
3212 if (IsUnsigned) {
3213 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3214 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3215 // the pseudo-branch will be taken only when the non-zero register is
3216 // different from 0, so we emit a BNEZ.
3217 //
3218 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3219 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3220 // the pseudo-branch will be taken only when the non-zero register is
3221 // equal to 0, so we emit a BEQZ.
3222 //
3223 // Because only BLEU and BGEU branch on equality, we can use the
3224 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003225 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3226 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3227 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003228 return false;
3229 }
3230 // If we have a signed pseudo-branch and one of the registers is $0,
3231 // we can use an appropriate compare-to-zero branch. We select which one
3232 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003233 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3234 IsSrcRegZero ? TrgReg : SrcReg,
3235 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003236 return false;
3237 }
3238
3239 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3240 // expansions. If it is not available, we return.
3241 unsigned ATRegNum = getATReg(IDLoc);
3242 if (!ATRegNum)
3243 return true;
3244
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003245 if (!EmittedNoMacroWarning)
3246 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003247
3248 // SLT fits well with 2 of our 4 pseudo-branches:
3249 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3250 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3251 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3252 // This is accomplished by using a BNEZ with the result of the SLT.
3253 //
3254 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3255 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3256 // Because only BGE and BLE branch on equality, we can use the
3257 // AcceptsEquality variable to decide when to emit the BEQZ.
3258 // Note that the order of the SLT arguments doesn't change between
3259 // opposites.
3260 //
3261 // The same applies to the unsigned variants, except that SLTu is used
3262 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003263 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3264 ReverseOrderSLT ? TrgReg : SrcReg,
3265 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003266
Daniel Sandersa736b372016-04-29 13:33:12 +00003267 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3268 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3269 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3270 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003271 return false;
3272}
3273
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003274bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3275 const MCSubtargetInfo *STI, const bool IsMips64,
3276 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003277 MipsTargetStreamer &TOut = getTargetStreamer();
3278
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003279 warnIfNoMacro(IDLoc);
3280
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003281 const MCOperand &RdRegOp = Inst.getOperand(0);
3282 assert(RdRegOp.isReg() && "expected register operand kind");
3283 unsigned RdReg = RdRegOp.getReg();
3284
3285 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003286 assert(RsRegOp.isReg() && "expected register operand kind");
3287 unsigned RsReg = RsRegOp.getReg();
3288
Simon Dardis12850ee2017-01-31 10:49:24 +00003289 unsigned RtReg;
3290 int64_t ImmValue;
3291
3292 const MCOperand &RtOp = Inst.getOperand(2);
3293 assert((RtOp.isReg() || RtOp.isImm()) &&
3294 "expected register or immediate operand kind");
3295 if (RtOp.isReg())
3296 RtReg = RtOp.getReg();
3297 else
3298 ImmValue = RtOp.getImm();
3299
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003300 unsigned DivOp;
3301 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003302 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003303
3304 if (IsMips64) {
3305 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3306 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003307 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003308 } else {
3309 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3310 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003311 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003312 }
3313
3314 bool UseTraps = useTraps();
3315
Simon Dardis12850ee2017-01-31 10:49:24 +00003316 if (RtOp.isImm()) {
3317 unsigned ATReg = getATReg(IDLoc);
3318 if (!ATReg)
3319 return true;
3320
3321 if (ImmValue == 0) {
3322 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64)
3323 Warning(IDLoc, "dividing zero by zero");
3324 else
3325 Warning(IDLoc, "division by zero");
3326 if (UseTraps)
3327 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3328 else
3329 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3330 return false;
3331 }
3332
3333 if (ImmValue == 1) {
3334 TOut.emitRRR(Mips::ADDu, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
3335 return false;
3336 } else if (Signed && ImmValue == -1) {
3337 TOut.emitRRR(SubOp, RdReg, Mips::ZERO, RsReg, IDLoc, STI);
3338 return false;
3339 } else {
3340 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
3341 false, Inst.getLoc(), Out, STI))
3342 return true;
3343 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
3344 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
3345 return false;
3346 }
3347 return true;
3348 }
3349
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003350 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
3351 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
3352 Warning(IDLoc, "dividing zero by zero");
3353 if (IsMips64) {
3354 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
3355 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003356 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003357 return false;
3358 }
3359
Daniel Sandersa736b372016-04-29 13:33:12 +00003360 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003361 return false;
3362 }
3363 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00003364 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003365 return false;
3366 }
3367 }
3368
3369 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3370 Warning(IDLoc, "division by zero");
3371 if (Signed) {
3372 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003373 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003374 return false;
3375 }
3376
Daniel Sandersa736b372016-04-29 13:33:12 +00003377 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003378 return false;
3379 }
3380 }
3381
3382 // FIXME: The values for these two BranchTarget variables may be different in
3383 // micromips. These magic numbers need to be removed.
3384 unsigned BranchTargetNoTraps;
3385 unsigned BranchTarget;
3386
3387 if (UseTraps) {
3388 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003389 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003390 } else {
3391 BranchTarget = IsMips64 ? 20 : 16;
3392 BranchTargetNoTraps = 8;
3393 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003394 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003395 }
3396
Daniel Sandersa736b372016-04-29 13:33:12 +00003397 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003398
3399 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003400 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003401
3402 if (!Signed) {
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003403 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003404 return false;
3405 }
3406
3407 unsigned ATReg = getATReg(IDLoc);
3408 if (!ATReg)
3409 return true;
3410
Daniel Sandersa736b372016-04-29 13:33:12 +00003411 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003412 if (IsMips64) {
3413 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003414 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3415 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3416 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003417 } else {
3418 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003419 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3420 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003421 }
3422
3423 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003424 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003425 else {
3426 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003427 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3428 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3429 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003430 }
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003431 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003432 return false;
3433}
3434
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003435bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003436 SMLoc IDLoc, MCStreamer &Out,
3437 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003438 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003439
3440 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3441 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3442 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3443
3444 unsigned FirstReg = Inst.getOperand(0).getReg();
3445 unsigned SecondReg = Inst.getOperand(1).getReg();
3446 unsigned ThirdReg = Inst.getOperand(2).getReg();
3447
3448 if (hasMips1() && !hasMips2()) {
3449 unsigned ATReg = getATReg(IDLoc);
3450 if (!ATReg)
3451 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003452 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3453 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3454 TOut.emitNop(IDLoc, STI);
3455 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3456 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3457 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3458 TOut.emitNop(IDLoc, STI);
3459 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3460 : Mips::CVT_W_S,
3461 FirstReg, SecondReg, IDLoc, STI);
3462 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3463 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003464 return false;
3465 }
3466
Daniel Sandersa736b372016-04-29 13:33:12 +00003467 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3468 : Mips::TRUNC_W_S,
3469 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003470
3471 return false;
3472}
3473
Daniel Sanders6394ee52015-10-15 14:52:58 +00003474bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003475 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003476 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003477 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003478 }
3479
Toma Tabacud88d79c2015-06-23 14:39:42 +00003480 const MCOperand &DstRegOp = Inst.getOperand(0);
3481 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003482 const MCOperand &SrcRegOp = Inst.getOperand(1);
3483 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003484 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3485 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3486
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003487 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00003488 unsigned DstReg = DstRegOp.getReg();
3489 unsigned SrcReg = SrcRegOp.getReg();
3490 int64_t OffsetValue = OffsetImmOp.getImm();
3491
3492 // NOTE: We always need AT for ULHU, as it is always used as the source
3493 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003494 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003495 unsigned ATReg = getATReg(IDLoc);
3496 if (!ATReg)
3497 return true;
3498
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003499 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
3500 if (IsLargeOffset) {
3501 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
3502 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003503 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00003504 }
3505
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003506 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
3507 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
3508 if (isLittle())
3509 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003510
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003511 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
3512 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00003513
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003514 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
3515 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00003516
Daniel Sandersa736b372016-04-29 13:33:12 +00003517 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003518 FirstOffset, IDLoc, STI);
3519 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00003520 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00003521 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003522
3523 return false;
3524}
3525
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003526bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003527 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003528 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003529 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003530 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003531
3532 const MCOperand &DstRegOp = Inst.getOperand(0);
3533 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003534 const MCOperand &SrcRegOp = Inst.getOperand(1);
3535 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003536 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3537 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3538
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003539 MipsTargetStreamer &TOut = getTargetStreamer();
3540 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003541 unsigned SrcReg = SrcRegOp.getReg();
3542 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003543
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003544 warnIfNoMacro(IDLoc);
3545 unsigned ATReg = getATReg(IDLoc);
3546 if (!ATReg)
3547 return true;
3548
3549 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
3550 if (IsLargeOffset) {
3551 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
3552 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003553 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003554 }
3555
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003556 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
3557 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
3558 if (isLittle())
3559 std::swap(FirstOffset, SecondOffset);
3560
3561 if (IsLargeOffset) {
3562 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
3563 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
3564 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
3565 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
3566 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
3567 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003568 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003569 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
3570 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
3571 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003572 }
3573
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003574 return false;
3575}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003576
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003577bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3578 const MCSubtargetInfo *STI) {
3579 if (hasMips32r6() || hasMips64r6()) {
3580 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3581 }
3582
3583 const MCOperand &DstRegOp = Inst.getOperand(0);
3584 assert(DstRegOp.isReg() && "expected register operand kind");
3585 const MCOperand &SrcRegOp = Inst.getOperand(1);
3586 assert(SrcRegOp.isReg() && "expected register operand kind");
3587 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3588 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3589
3590 MipsTargetStreamer &TOut = getTargetStreamer();
3591 unsigned DstReg = DstRegOp.getReg();
3592 unsigned SrcReg = SrcRegOp.getReg();
3593 int64_t OffsetValue = OffsetImmOp.getImm();
3594
3595 // Compute left/right load/store offsets.
3596 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
3597 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
3598 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
3599 if (isLittle())
3600 std::swap(LxlOffset, LxrOffset);
3601
3602 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
3603 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
3604 unsigned TmpReg = SrcReg;
3605 if (IsLargeOffset || DoMove) {
3606 warnIfNoMacro(IDLoc);
3607 TmpReg = getATReg(IDLoc);
3608 if (!TmpReg)
3609 return true;
3610 }
3611
3612 if (IsLargeOffset) {
3613 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
3614 IDLoc, Out, STI))
3615 return true;
3616 }
3617
3618 if (DoMove)
3619 std::swap(DstReg, TmpReg);
3620
3621 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
3622 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
3623 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
3624 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
3625
3626 if (DoMove)
3627 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003628
3629 return false;
3630}
3631
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003632bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003633 MCStreamer &Out,
3634 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003635 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003636
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003637 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3638 assert(Inst.getOperand(0).isReg() &&
3639 Inst.getOperand(1).isReg() &&
3640 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003641
3642 unsigned ATReg = Mips::NoRegister;
3643 unsigned FinalDstReg = Mips::NoRegister;
3644 unsigned DstReg = Inst.getOperand(0).getReg();
3645 unsigned SrcReg = Inst.getOperand(1).getReg();
3646 int64_t ImmValue = Inst.getOperand(2).getImm();
3647
3648 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3649
3650 unsigned FinalOpcode = Inst.getOpcode();
3651
3652 if (DstReg == SrcReg) {
3653 ATReg = getATReg(Inst.getLoc());
3654 if (!ATReg)
3655 return true;
3656 FinalDstReg = DstReg;
3657 DstReg = ATReg;
3658 }
3659
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003660 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003661 switch (FinalOpcode) {
3662 default:
3663 llvm_unreachable("unimplemented expansion");
3664 case (Mips::ADDi):
3665 FinalOpcode = Mips::ADD;
3666 break;
3667 case (Mips::ADDiu):
3668 FinalOpcode = Mips::ADDu;
3669 break;
3670 case (Mips::ANDi):
3671 FinalOpcode = Mips::AND;
3672 break;
3673 case (Mips::NORImm):
3674 FinalOpcode = Mips::NOR;
3675 break;
3676 case (Mips::ORi):
3677 FinalOpcode = Mips::OR;
3678 break;
3679 case (Mips::SLTi):
3680 FinalOpcode = Mips::SLT;
3681 break;
3682 case (Mips::SLTiu):
3683 FinalOpcode = Mips::SLTu;
3684 break;
3685 case (Mips::XORi):
3686 FinalOpcode = Mips::XOR;
3687 break;
3688 }
3689
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003690 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003691 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003692 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003693 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003694 return false;
3695 }
3696 return true;
3697}
3698
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003699bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3700 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003701 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003702 unsigned ATReg = Mips::NoRegister;
3703 unsigned DReg = Inst.getOperand(0).getReg();
3704 unsigned SReg = Inst.getOperand(1).getReg();
3705 unsigned TReg = Inst.getOperand(2).getReg();
3706 unsigned TmpReg = DReg;
3707
3708 unsigned FirstShift = Mips::NOP;
3709 unsigned SecondShift = Mips::NOP;
3710
3711 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003712 if (DReg == SReg) {
3713 TmpReg = getATReg(Inst.getLoc());
3714 if (!TmpReg)
3715 return true;
3716 }
3717
3718 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003719 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3720 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003721 return false;
3722 }
3723
3724 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003725 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003726 return false;
3727 }
3728
3729 return true;
3730 }
3731
3732 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003733 switch (Inst.getOpcode()) {
3734 default:
3735 llvm_unreachable("unexpected instruction opcode");
3736 case Mips::ROL:
3737 FirstShift = Mips::SRLV;
3738 SecondShift = Mips::SLLV;
3739 break;
3740 case Mips::ROR:
3741 FirstShift = Mips::SLLV;
3742 SecondShift = Mips::SRLV;
3743 break;
3744 }
3745
3746 ATReg = getATReg(Inst.getLoc());
3747 if (!ATReg)
3748 return true;
3749
Daniel Sandersa736b372016-04-29 13:33:12 +00003750 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3751 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3752 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3753 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003754
3755 return false;
3756 }
3757
3758 return true;
3759}
3760
3761bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003762 MCStreamer &Out,
3763 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003764 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003765 unsigned ATReg = Mips::NoRegister;
3766 unsigned DReg = Inst.getOperand(0).getReg();
3767 unsigned SReg = Inst.getOperand(1).getReg();
3768 int64_t ImmValue = Inst.getOperand(2).getImm();
3769
3770 unsigned FirstShift = Mips::NOP;
3771 unsigned SecondShift = Mips::NOP;
3772
3773 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003774 if (Inst.getOpcode() == Mips::ROLImm) {
3775 uint64_t MaxShift = 32;
3776 uint64_t ShiftValue = ImmValue;
3777 if (ImmValue != 0)
3778 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003779 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003780 return false;
3781 }
3782
3783 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003784 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003785 return false;
3786 }
3787
3788 return true;
3789 }
3790
3791 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003792 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003793 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003794 return false;
3795 }
3796
3797 switch (Inst.getOpcode()) {
3798 default:
3799 llvm_unreachable("unexpected instruction opcode");
3800 case Mips::ROLImm:
3801 FirstShift = Mips::SLL;
3802 SecondShift = Mips::SRL;
3803 break;
3804 case Mips::RORImm:
3805 FirstShift = Mips::SRL;
3806 SecondShift = Mips::SLL;
3807 break;
3808 }
3809
3810 ATReg = getATReg(Inst.getLoc());
3811 if (!ATReg)
3812 return true;
3813
Daniel Sandersa736b372016-04-29 13:33:12 +00003814 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3815 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3816 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003817
3818 return false;
3819 }
3820
3821 return true;
3822}
3823
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003824bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3825 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003826 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003827 unsigned ATReg = Mips::NoRegister;
3828 unsigned DReg = Inst.getOperand(0).getReg();
3829 unsigned SReg = Inst.getOperand(1).getReg();
3830 unsigned TReg = Inst.getOperand(2).getReg();
3831 unsigned TmpReg = DReg;
3832
3833 unsigned FirstShift = Mips::NOP;
3834 unsigned SecondShift = Mips::NOP;
3835
3836 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003837 if (TmpReg == SReg) {
3838 TmpReg = getATReg(Inst.getLoc());
3839 if (!TmpReg)
3840 return true;
3841 }
3842
3843 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003844 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3845 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003846 return false;
3847 }
3848
3849 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003850 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003851 return false;
3852 }
3853
3854 return true;
3855 }
3856
3857 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003858 switch (Inst.getOpcode()) {
3859 default:
3860 llvm_unreachable("unexpected instruction opcode");
3861 case Mips::DROL:
3862 FirstShift = Mips::DSRLV;
3863 SecondShift = Mips::DSLLV;
3864 break;
3865 case Mips::DROR:
3866 FirstShift = Mips::DSLLV;
3867 SecondShift = Mips::DSRLV;
3868 break;
3869 }
3870
3871 ATReg = getATReg(Inst.getLoc());
3872 if (!ATReg)
3873 return true;
3874
Daniel Sandersa736b372016-04-29 13:33:12 +00003875 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3876 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3877 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3878 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003879
3880 return false;
3881 }
3882
3883 return true;
3884}
3885
3886bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003887 MCStreamer &Out,
3888 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003889 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003890 unsigned ATReg = Mips::NoRegister;
3891 unsigned DReg = Inst.getOperand(0).getReg();
3892 unsigned SReg = Inst.getOperand(1).getReg();
3893 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3894
3895 unsigned FirstShift = Mips::NOP;
3896 unsigned SecondShift = Mips::NOP;
3897
3898 MCInst TmpInst;
3899
3900 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003901 unsigned FinalOpcode = Mips::NOP;
3902 if (ImmValue == 0)
3903 FinalOpcode = Mips::DROTR;
3904 else if (ImmValue % 32 == 0)
3905 FinalOpcode = Mips::DROTR32;
3906 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3907 if (Inst.getOpcode() == Mips::DROLImm)
3908 FinalOpcode = Mips::DROTR32;
3909 else
3910 FinalOpcode = Mips::DROTR;
3911 } else if (ImmValue >= 33) {
3912 if (Inst.getOpcode() == Mips::DROLImm)
3913 FinalOpcode = Mips::DROTR;
3914 else
3915 FinalOpcode = Mips::DROTR32;
3916 }
3917
3918 uint64_t ShiftValue = ImmValue % 32;
3919 if (Inst.getOpcode() == Mips::DROLImm)
3920 ShiftValue = (32 - ImmValue % 32) % 32;
3921
Daniel Sandersa736b372016-04-29 13:33:12 +00003922 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003923
3924 return false;
3925 }
3926
3927 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003928 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003929 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003930 return false;
3931 }
3932
3933 switch (Inst.getOpcode()) {
3934 default:
3935 llvm_unreachable("unexpected instruction opcode");
3936 case Mips::DROLImm:
3937 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3938 FirstShift = Mips::DSLL;
3939 SecondShift = Mips::DSRL32;
3940 }
3941 if (ImmValue == 32) {
3942 FirstShift = Mips::DSLL32;
3943 SecondShift = Mips::DSRL32;
3944 }
3945 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3946 FirstShift = Mips::DSLL32;
3947 SecondShift = Mips::DSRL;
3948 }
3949 break;
3950 case Mips::DRORImm:
3951 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3952 FirstShift = Mips::DSRL;
3953 SecondShift = Mips::DSLL32;
3954 }
3955 if (ImmValue == 32) {
3956 FirstShift = Mips::DSRL32;
3957 SecondShift = Mips::DSLL32;
3958 }
3959 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3960 FirstShift = Mips::DSRL32;
3961 SecondShift = Mips::DSLL;
3962 }
3963 break;
3964 }
3965
3966 ATReg = getATReg(Inst.getLoc());
3967 if (!ATReg)
3968 return true;
3969
Daniel Sandersa736b372016-04-29 13:33:12 +00003970 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3971 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3972 Inst.getLoc(), STI);
3973 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003974
3975 return false;
3976 }
3977
3978 return true;
3979}
3980
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003981bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3982 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003983 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003984 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3985 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3986
Daniel Sandersa736b372016-04-29 13:33:12 +00003987 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003988 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003989 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003990 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003991 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3992 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003993
3994 return false;
3995}
3996
Simon Dardisaff4d142016-10-18 14:28:00 +00003997static unsigned nextReg(unsigned Reg) {
3998 switch (Reg) {
3999 case Mips::ZERO: return Mips::AT;
4000 case Mips::AT: return Mips::V0;
4001 case Mips::V0: return Mips::V1;
4002 case Mips::V1: return Mips::A0;
4003 case Mips::A0: return Mips::A1;
4004 case Mips::A1: return Mips::A2;
4005 case Mips::A2: return Mips::A3;
4006 case Mips::A3: return Mips::T0;
4007 case Mips::T0: return Mips::T1;
4008 case Mips::T1: return Mips::T2;
4009 case Mips::T2: return Mips::T3;
4010 case Mips::T3: return Mips::T4;
4011 case Mips::T4: return Mips::T5;
4012 case Mips::T5: return Mips::T6;
4013 case Mips::T6: return Mips::T7;
4014 case Mips::T7: return Mips::S0;
4015 case Mips::S0: return Mips::S1;
4016 case Mips::S1: return Mips::S2;
4017 case Mips::S2: return Mips::S3;
4018 case Mips::S3: return Mips::S4;
4019 case Mips::S4: return Mips::S5;
4020 case Mips::S5: return Mips::S6;
4021 case Mips::S6: return Mips::S7;
4022 case Mips::S7: return Mips::T8;
4023 case Mips::T8: return Mips::T9;
4024 case Mips::T9: return Mips::K0;
4025 case Mips::K0: return Mips::K1;
4026 case Mips::K1: return Mips::GP;
4027 case Mips::GP: return Mips::SP;
4028 case Mips::SP: return Mips::FP;
4029 case Mips::FP: return Mips::RA;
4030 case Mips::RA: return Mips::ZERO;
4031 default: return 0;
4032 }
4033
4034}
4035
4036// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4037// lw $<reg+1>>, offset+4($reg2)'
4038// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4039// sw $<reg+1>>, offset+4($reg2)'
4040// for O32.
4041bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4042 MCStreamer &Out,
4043 const MCSubtargetInfo *STI,
4044 bool IsLoad) {
4045 if (!isABI_O32())
4046 return true;
4047
4048 warnIfNoMacro(IDLoc);
4049
4050 MipsTargetStreamer &TOut = getTargetStreamer();
4051 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4052 unsigned FirstReg = Inst.getOperand(0).getReg();
4053 unsigned SecondReg = nextReg(FirstReg);
4054 unsigned BaseReg = Inst.getOperand(1).getReg();
4055 if (!SecondReg)
4056 return true;
4057
4058 warnIfRegIndexIsAT(FirstReg, IDLoc);
4059
4060 assert(Inst.getOperand(2).isImm() &&
4061 "Offset for load macro is not immediate!");
4062
4063 MCOperand &FirstOffset = Inst.getOperand(2);
4064 signed NextOffset = FirstOffset.getImm() + 4;
4065 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4066
4067 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4068 return true;
4069
4070 // For loads, clobber the base register with the second load instead of the
4071 // first if the BaseReg == FirstReg.
4072 if (FirstReg != BaseReg || !IsLoad) {
4073 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4074 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4075 } else {
4076 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4077 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4078 }
4079
4080 return false;
4081}
4082
Simon Dardis43115a12016-11-21 20:30:41 +00004083bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4084 const MCSubtargetInfo *STI) {
4085
4086 warnIfNoMacro(IDLoc);
4087 MipsTargetStreamer &TOut = getTargetStreamer();
4088
4089 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4090 Inst.getOperand(2).getReg() != Mips::ZERO) {
4091 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4092 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4093 IDLoc, STI);
4094 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4095 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4096 return false;
4097 }
4098
4099 unsigned Reg = 0;
4100 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4101 Reg = Inst.getOperand(2).getReg();
4102 } else {
4103 Reg = Inst.getOperand(1).getReg();
4104 }
4105 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4106 return false;
4107}
4108
4109bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4110 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004111 warnIfNoMacro(IDLoc);
4112 MipsTargetStreamer &TOut = getTargetStreamer();
4113
4114 unsigned Opc;
4115 int64_t Imm = Inst.getOperand(2).getImm();
4116 unsigned Reg = Inst.getOperand(1).getReg();
4117
4118 if (Imm == 0) {
4119 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4120 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4121 return false;
4122 } else {
4123
4124 if (Reg == Mips::ZERO) {
4125 Warning(IDLoc, "comparison is always false");
4126 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4127 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4128 return false;
4129 }
4130
4131 if (Imm > -0x8000 && Imm < 0) {
4132 Imm = -Imm;
4133 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4134 } else {
4135 Opc = Mips::XORi;
4136 }
4137 }
4138 if (!isUInt<16>(Imm)) {
4139 unsigned ATReg = getATReg(IDLoc);
4140 if (!ATReg)
4141 return true;
4142
4143 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4144 Out, STI))
4145 return true;
4146
4147 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4148 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4149 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4150 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4151 return false;
4152 }
4153
4154 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4155 Imm, IDLoc, STI);
4156 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4157 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4158 return false;
4159}
4160
Daniel Sandersc5537422016-07-27 13:49:44 +00004161unsigned
4162MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
4163 const OperandVector &Operands) {
4164 switch (Inst.getOpcode()) {
4165 default:
4166 return Match_Success;
4167 case Mips::DATI:
4168 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00004169 case Mips::DATI_MM64R6:
4170 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00004171 if (static_cast<MipsOperand &>(*Operands[1])
4172 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
4173 return Match_Success;
4174 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00004175 }
4176}
Simon Dardis730fdb72017-01-16 13:55:58 +00004177
Matheus Almeida595fcab2014-06-11 15:05:56 +00004178unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00004179 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00004180 // As described by the MIPSR6 spec, daui must not use the zero operand for
4181 // its source operand.
4182 case Mips::DAUI:
4183 case Mips::DAUI_MM64R6:
4184 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4185 Inst.getOperand(1).getReg() == Mips::ZERO_64)
4186 return Match_RequiresNoZeroRegister;
4187 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00004188 // As described by the Mips32r2 spec, the registers Rd and Rs for
4189 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00004190 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00004191 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00004192 case Mips::JALR_HB:
4193 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00004194 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00004195 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4196 return Match_RequiresDifferentSrcAndDst;
4197 return Match_Success;
4198 case Mips::LWP_MM:
4199 case Mips::LWP_MMR6:
4200 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
4201 return Match_RequiresDifferentSrcAndDst;
4202 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00004203 case Mips::SYNC:
4204 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
4205 return Match_NonZeroOperandForSync;
4206 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004207 // As described the MIPSR6 spec, the compact branches that compare registers
4208 // must:
4209 // a) Not use the zero register.
4210 // b) Not use the same register twice.
4211 // c) rs < rt for bnec, beqc.
4212 // NB: For this case, the encoding will swap the operands as their
4213 // ordering doesn't matter. GAS performs this transformation too.
4214 // Hence, that constraint does not have to be enforced.
4215 //
4216 // The compact branches that branch iff the signed addition of two registers
4217 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
4218 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004219 case Mips::BLEZC: case Mips::BLEZC_MMR6:
4220 case Mips::BGEZC: case Mips::BGEZC_MMR6:
4221 case Mips::BGTZC: case Mips::BGTZC_MMR6:
4222 case Mips::BLTZC: case Mips::BLTZC_MMR6:
4223 case Mips::BEQZC: case Mips::BEQZC_MMR6:
4224 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004225 case Mips::BLEZC64:
4226 case Mips::BGEZC64:
4227 case Mips::BGTZC64:
4228 case Mips::BLTZC64:
4229 case Mips::BEQZC64:
4230 case Mips::BNEZC64:
4231 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4232 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004233 return Match_RequiresNoZeroRegister;
4234 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004235 case Mips::BGEC: case Mips::BGEC_MMR6:
4236 case Mips::BLTC: case Mips::BLTC_MMR6:
4237 case Mips::BGEUC: case Mips::BGEUC_MMR6:
4238 case Mips::BLTUC: case Mips::BLTUC_MMR6:
4239 case Mips::BEQC: case Mips::BEQC_MMR6:
4240 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004241 case Mips::BGEC64:
4242 case Mips::BLTC64:
4243 case Mips::BGEUC64:
4244 case Mips::BLTUC64:
4245 case Mips::BEQC64:
4246 case Mips::BNEC64:
4247 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4248 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004249 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00004250 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4251 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004252 return Match_RequiresNoZeroRegister;
4253 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4254 return Match_RequiresDifferentOperands;
4255 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004256 }
Simon Dardis730fdb72017-01-16 13:55:58 +00004257
4258 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
4259 if ((TSFlags & MipsII::HasFCCRegOperand) &&
4260 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
4261 return Match_NoFCCRegisterForCurrentISA;
4262
4263 return Match_Success;
4264
Matheus Almeida595fcab2014-06-11 15:05:56 +00004265}
4266
Daniel Sanders52da7af2015-11-06 12:11:03 +00004267static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
4268 uint64_t ErrorInfo) {
4269 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
4270 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
4271 if (ErrorLoc == SMLoc())
4272 return Loc;
4273 return ErrorLoc;
4274 }
4275 return Loc;
4276}
4277
David Blaikie960ea3f2014-06-08 16:18:35 +00004278bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4279 OperandVector &Operands,
4280 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004281 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00004282 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004283 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00004284 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004285 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00004286
4287 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004288 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004289 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00004290 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004291 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00004292 case Match_MissingFeature:
4293 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4294 return true;
4295 case Match_InvalidOperand: {
4296 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00004297 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004298 if (ErrorInfo >= Operands.size())
4299 return Error(IDLoc, "too few operands for instruction");
4300
Daniel Sanders52da7af2015-11-06 12:11:03 +00004301 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00004302 if (ErrorLoc == SMLoc())
4303 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00004304 }
4305
4306 return Error(ErrorLoc, "invalid operand for instruction");
4307 }
Simon Dardisc4463c92016-10-18 14:42:13 +00004308 case Match_NonZeroOperandForSync:
4309 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00004310 case Match_MnemonicFail:
4311 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00004312 case Match_RequiresDifferentSrcAndDst:
4313 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00004314 case Match_RequiresDifferentOperands:
4315 return Error(IDLoc, "registers must be different");
4316 case Match_RequiresNoZeroRegister:
4317 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00004318 case Match_RequiresSameSrcAndDst:
4319 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00004320 case Match_NoFCCRegisterForCurrentISA:
4321 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4322 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00004323 case Match_Immz:
4324 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004325 case Match_UImm1_0:
4326 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4327 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00004328 case Match_UImm2_0:
4329 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4330 "expected 2-bit unsigned immediate");
4331 case Match_UImm2_1:
4332 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4333 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00004334 case Match_UImm3_0:
4335 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4336 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004337 case Match_UImm4_0:
4338 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4339 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00004340 case Match_SImm4_0:
4341 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4342 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004343 case Match_UImm5_0:
4344 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4345 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00004346 case Match_SImm5_0:
4347 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4348 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004349 case Match_UImm5_1:
4350 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4351 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004352 case Match_UImm5_32:
4353 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4354 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004355 case Match_UImm5_33:
4356 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4357 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004358 case Match_UImm5_0_Report_UImm6:
4359 // This is used on UImm5 operands that have a corresponding UImm5_32
4360 // operand to avoid confusing the user.
4361 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4362 "expected 6-bit unsigned immediate");
4363 case Match_UImm5_Lsl2:
4364 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4365 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00004366 case Match_UImmRange2_64:
4367 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4368 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00004369 case Match_UImm6_0:
4370 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4371 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00004372 case Match_UImm6_Lsl2:
4373 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4374 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00004375 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00004376 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4377 "expected 6-bit signed immediate");
4378 case Match_UImm7_0:
4379 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4380 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00004381 case Match_UImm7_N1:
4382 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4383 "expected immediate in range -1 .. 126");
4384 case Match_SImm7_Lsl2:
4385 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4386 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00004387 case Match_UImm8_0:
4388 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4389 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00004390 case Match_UImm10_0:
4391 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4392 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00004393 case Match_SImm10_0:
4394 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4395 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00004396 case Match_SImm11_0:
4397 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4398 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00004399 case Match_UImm16:
4400 case Match_UImm16_Relaxed:
4401 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4402 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004403 case Match_SImm16:
4404 case Match_SImm16_Relaxed:
4405 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4406 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00004407 case Match_SImm19_Lsl2:
4408 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4409 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00004410 case Match_UImm20_0:
4411 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4412 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00004413 case Match_UImm26_0:
4414 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4415 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00004416 case Match_SImm32:
4417 case Match_SImm32_Relaxed:
4418 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4419 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00004420 case Match_UImm32_Coerced:
4421 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4422 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00004423 case Match_MemSImm9:
4424 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4425 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00004426 case Match_MemSImm10:
4427 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4428 "expected memory with 10-bit signed offset");
4429 case Match_MemSImm10Lsl1:
4430 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4431 "expected memory with 11-bit signed offset and multiple of 2");
4432 case Match_MemSImm10Lsl2:
4433 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4434 "expected memory with 12-bit signed offset and multiple of 4");
4435 case Match_MemSImm10Lsl3:
4436 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4437 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00004438 case Match_MemSImm11:
4439 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4440 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00004441 case Match_MemSImm12:
4442 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4443 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004444 case Match_MemSImm16:
4445 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4446 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00004447 }
Craig Topper589ceee2015-01-03 08:16:34 +00004448
4449 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00004450}
4451
Toma Tabacud9d344b2015-04-27 14:05:04 +00004452void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
4453 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
4454 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
4455 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004456}
4457
Toma Tabacu81496c12015-05-20 08:54:45 +00004458void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
4459 if (!AssemblerOptions.back()->isMacro())
4460 Warning(Loc, "macro instruction expanded into multiple instructions");
4461}
4462
Daniel Sandersef638fe2014-10-03 15:37:37 +00004463void
4464MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
4465 SMRange Range, bool ShowColors) {
4466 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00004467 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00004468 ShowColors);
4469}
4470
Jack Carter1ac53222013-02-20 23:11:17 +00004471int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004472 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004473
Vladimir Medic4c299852013-11-06 11:27:05 +00004474 CC = StringSwitch<unsigned>(Name)
4475 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004476 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00004477 .Case("a0", 4)
4478 .Case("a1", 5)
4479 .Case("a2", 6)
4480 .Case("a3", 7)
4481 .Case("v0", 2)
4482 .Case("v1", 3)
4483 .Case("s0", 16)
4484 .Case("s1", 17)
4485 .Case("s2", 18)
4486 .Case("s3", 19)
4487 .Case("s4", 20)
4488 .Case("s5", 21)
4489 .Case("s6", 22)
4490 .Case("s7", 23)
4491 .Case("k0", 26)
4492 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004493 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00004494 .Case("sp", 29)
4495 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004496 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00004497 .Case("ra", 31)
4498 .Case("t0", 8)
4499 .Case("t1", 9)
4500 .Case("t2", 10)
4501 .Case("t3", 11)
4502 .Case("t4", 12)
4503 .Case("t5", 13)
4504 .Case("t6", 14)
4505 .Case("t7", 15)
4506 .Case("t8", 24)
4507 .Case("t9", 25)
4508 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004509
Toma Tabacufda445c2014-09-15 15:33:01 +00004510 if (!(isABI_N32() || isABI_N64()))
4511 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004512
Daniel Sandersef638fe2014-10-03 15:37:37 +00004513 if (12 <= CC && CC <= 15) {
4514 // Name is one of t4-t7
4515 AsmToken RegTok = getLexer().peekTok();
4516 SMRange RegRange = RegTok.getLocRange();
4517
4518 StringRef FixedName = StringSwitch<StringRef>(Name)
4519 .Case("t4", "t0")
4520 .Case("t5", "t1")
4521 .Case("t6", "t2")
4522 .Case("t7", "t3")
4523 .Default("");
4524 assert(FixedName != "" && "Register name is not one of t4-t7.");
4525
4526 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
4527 "Did you mean $" + FixedName + "?", RegRange);
4528 }
4529
Toma Tabacufda445c2014-09-15 15:33:01 +00004530 // Although SGI documentation just cuts out t0-t3 for n32/n64,
4531 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
4532 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
4533 if (8 <= CC && CC <= 11)
4534 CC += 4;
4535
4536 if (CC == -1)
4537 CC = StringSwitch<unsigned>(Name)
4538 .Case("a4", 8)
4539 .Case("a5", 9)
4540 .Case("a6", 10)
4541 .Case("a7", 11)
4542 .Case("kt0", 26)
4543 .Case("kt1", 27)
4544 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004545
4546 return CC;
4547}
Jack Carterd0bd6422013-04-18 00:41:53 +00004548
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004549int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
4550 int CC;
4551
4552 CC = StringSwitch<unsigned>(Name)
4553 .Case("hwr_cpunum", 0)
4554 .Case("hwr_synci_step", 1)
4555 .Case("hwr_cc", 2)
4556 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00004557 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004558 .Default(-1);
4559
4560 return CC;
4561}
4562
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004563int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00004564 if (Name[0] == 'f') {
4565 StringRef NumString = Name.substr(1);
4566 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004567 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004568 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004569 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00004570 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004571 return IntVal;
4572 }
4573 return -1;
4574}
Jack Cartera63b16a2012-09-07 00:23:42 +00004575
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004576int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004577 if (Name.startswith("fcc")) {
4578 StringRef NumString = Name.substr(3);
4579 unsigned IntVal;
4580 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004581 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004582 if (IntVal > 7) // There are only 8 fcc registers.
4583 return -1;
4584 return IntVal;
4585 }
4586 return -1;
4587}
4588
4589int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00004590 if (Name.startswith("ac")) {
4591 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004592 unsigned IntVal;
4593 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004594 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004595 if (IntVal > 3) // There are only 3 acc registers.
4596 return -1;
4597 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00004598 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004599 return -1;
4600}
Jack Carterd0bd6422013-04-18 00:41:53 +00004601
Jack Carter5dc8ac92013-09-25 23:50:44 +00004602int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
4603 unsigned IntVal;
4604
4605 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
4606 return -1;
4607
4608 if (IntVal > 31)
4609 return -1;
4610
4611 return IntVal;
4612}
4613
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004614int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
4615 int CC;
4616
4617 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00004618 .Case("msair", 0)
4619 .Case("msacsr", 1)
4620 .Case("msaaccess", 2)
4621 .Case("msasave", 3)
4622 .Case("msamodify", 4)
4623 .Case("msarequest", 5)
4624 .Case("msamap", 6)
4625 .Case("msaunmap", 7)
4626 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004627
4628 return CC;
4629}
4630
Toma Tabacu89a712b2015-04-15 10:48:56 +00004631unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004632 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004633 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004634 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004635 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004636 return 0;
4637 }
4638 unsigned AT = getReg(
4639 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004640 return AT;
4641}
Jack Carter0b744b32012-10-04 02:29:46 +00004642
Jack Carterd0bd6422013-04-18 00:41:53 +00004643unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004644 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004645}
4646
Toma Tabacu13964452014-09-04 13:23:44 +00004647bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004648 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004649 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004650
Jack Carter30a59822012-10-04 04:03:53 +00004651 // Check if the current operand has a custom associated parser, if so, try to
4652 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004653 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4654 if (ResTy == MatchOperand_Success)
4655 return false;
4656 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4657 // there was a match, but an error occurred, in which case, just return that
4658 // the operand parsing failed.
4659 if (ResTy == MatchOperand_ParseFail)
4660 return true;
4661
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004662 DEBUG(dbgs() << ".. Generic Parser\n");
4663
Jack Carterb4dbc172012-09-05 23:34:03 +00004664 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004665 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004666 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004667 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004668
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004669 // Almost all registers have been parsed by custom parsers. There is only
4670 // one exception to this. $zero (and it's alias $0) will reach this point
4671 // for div, divu, and similar instructions because it is not an operand
4672 // to the instruction definition but an explicit register. Special case
4673 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004674 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004675 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004676
Jack Carterd0bd6422013-04-18 00:41:53 +00004677 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004678 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004679 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004680 return true;
4681
Jack Carter873c7242013-01-12 01:03:14 +00004682 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004683 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004684 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004685 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004686 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004687
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004688 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004689 return false;
4690 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004691 default: {
4692 DEBUG(dbgs() << ".. generic integer expression\n");
4693
4694 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00004695 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004696 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004697 return true;
4698
Jack Carter873c7242013-01-12 01:03:14 +00004699 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4700
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004701 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004702 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004703 }
Jack Carter0b744b32012-10-04 02:29:46 +00004704 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004705 return true;
4706}
4707
Jack Carterb5cf5902013-04-17 00:18:04 +00004708bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004709 switch (Expr->getKind()) {
4710 case MCExpr::Constant:
4711 return true;
4712 case MCExpr::SymbolRef:
4713 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4714 case MCExpr::Binary:
4715 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4716 if (!isEvaluated(BE->getLHS()))
4717 return false;
4718 return isEvaluated(BE->getRHS());
4719 }
4720 case MCExpr::Unary:
4721 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004722 case MCExpr::Target:
4723 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004724 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004725 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004726}
Jack Carterd0bd6422013-04-18 00:41:53 +00004727
Jack Carterb4dbc172012-09-05 23:34:03 +00004728bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4729 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004730 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004731 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004732 if (ResTy == MatchOperand_Success) {
4733 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004734 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004735 StartLoc = Operand.getStartLoc();
4736 EndLoc = Operand.getEndLoc();
4737
4738 // AFAIK, we only support numeric registers and named GPR's in CFI
4739 // directives.
4740 // Don't worry about eating tokens before failing. Using an unrecognised
4741 // register is a parse error.
4742 if (Operand.isGPRAsmReg()) {
4743 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004744 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004745 }
4746
4747 return (RegNo == (unsigned)-1);
4748 }
4749
4750 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004751 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004752}
4753
Jack Carterb5cf5902013-04-17 00:18:04 +00004754bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00004755 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004756
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004757 if (isParenExpr)
4758 return getParser().parseParenExprOfDepth(0, Res, S);
4759 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004760}
4761
Alex Bradbury58eba092016-11-01 16:32:05 +00004762OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004763MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004764 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004765 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004766 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004767 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004768 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00004769 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004770 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004771 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004772
Jack Carterb5cf5902013-04-17 00:18:04 +00004773 if (getLexer().getKind() == AsmToken::LParen) {
4774 Parser.Lex();
4775 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004776 }
4777
Jack Carterb5cf5902013-04-17 00:18:04 +00004778 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004779 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004780 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004781
Jack Carterd0bd6422013-04-18 00:41:53 +00004782 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004783 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004784 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004785 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004786 SMLoc E =
4787 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004788 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004789 return MatchOperand_Success;
4790 }
4791 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004792 SMLoc E =
4793 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004794
Jack Carterd0bd6422013-04-18 00:41:53 +00004795 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004796 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00004797 auto Base = MipsOperand::createGPRReg(
4798 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00004799 Operands.push_back(
4800 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004801 return MatchOperand_Success;
4802 }
Simon Dardis858915f2016-10-18 15:17:17 +00004803 MCBinaryExpr::Opcode Opcode;
4804 // GAS and LLVM treat comparison operators different. GAS will generate -1
4805 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
4806 // highly unlikely to be found in a memory offset expression, we don't
4807 // handle them.
4808 switch (Tok.getKind()) {
4809 case AsmToken::Plus:
4810 Opcode = MCBinaryExpr::Add;
4811 Parser.Lex();
4812 break;
4813 case AsmToken::Minus:
4814 Opcode = MCBinaryExpr::Sub;
4815 Parser.Lex();
4816 break;
4817 case AsmToken::Star:
4818 Opcode = MCBinaryExpr::Mul;
4819 Parser.Lex();
4820 break;
4821 case AsmToken::Pipe:
4822 Opcode = MCBinaryExpr::Or;
4823 Parser.Lex();
4824 break;
4825 case AsmToken::Amp:
4826 Opcode = MCBinaryExpr::And;
4827 Parser.Lex();
4828 break;
4829 case AsmToken::LessLess:
4830 Opcode = MCBinaryExpr::Shl;
4831 Parser.Lex();
4832 break;
4833 case AsmToken::GreaterGreater:
4834 Opcode = MCBinaryExpr::LShr;
4835 Parser.Lex();
4836 break;
4837 case AsmToken::Caret:
4838 Opcode = MCBinaryExpr::Xor;
4839 Parser.Lex();
4840 break;
4841 case AsmToken::Slash:
4842 Opcode = MCBinaryExpr::Div;
4843 Parser.Lex();
4844 break;
4845 case AsmToken::Percent:
4846 Opcode = MCBinaryExpr::Mod;
4847 Parser.Lex();
4848 break;
4849 default:
4850 Error(Parser.getTok().getLoc(), "'(' or expression expected");
4851 return MatchOperand_ParseFail;
4852 }
4853 const MCExpr * NextExpr;
4854 if (getParser().parseExpression(NextExpr))
4855 return MatchOperand_ParseFail;
4856 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004857 }
4858
Jack Carterd0bd6422013-04-18 00:41:53 +00004859 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004860 }
4861
Toma Tabacu13964452014-09-04 13:23:44 +00004862 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004863 if (Res != MatchOperand_Success)
4864 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004865
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004866 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004867 Error(Parser.getTok().getLoc(), "')' expected");
4868 return MatchOperand_ParseFail;
4869 }
4870
Jack Carter873c7242013-01-12 01:03:14 +00004871 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4872
Jack Carterd0bd6422013-04-18 00:41:53 +00004873 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004874
Craig Topper062a2ba2014-04-25 05:30:21 +00004875 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004876 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004877
Jack Carterd0bd6422013-04-18 00:41:53 +00004878 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004879 std::unique_ptr<MipsOperand> op(
4880 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004881 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004882 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004883 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004884 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004885 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4886 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004887 if (IdVal->evaluateAsAbsolute(Imm))
4888 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004889 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004890 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004891 getContext());
4892 }
4893
David Blaikie960ea3f2014-06-08 16:18:35 +00004894 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004895 return MatchOperand_Success;
4896}
4897
David Blaikie960ea3f2014-06-08 16:18:35 +00004898bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004899 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004900 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004901 if (Sym) {
4902 SMLoc S = Parser.getTok().getLoc();
4903 const MCExpr *Expr;
4904 if (Sym->isVariable())
4905 Expr = Sym->getVariableValue();
4906 else
4907 return false;
4908 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004909 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004910 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004911 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004912 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004913 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004914 if (ResTy == MatchOperand_Success) {
4915 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004916 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004917 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004918 llvm_unreachable("Should never ParseFail");
4919 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004920 }
Jack Carterd76b2372013-03-21 21:44:16 +00004921 }
4922 }
4923 return false;
4924}
Jack Carterd0bd6422013-04-18 00:41:53 +00004925
Alex Bradbury58eba092016-11-01 16:32:05 +00004926OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004927MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004928 StringRef Identifier,
4929 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004930 int Index = matchCPURegisterName(Identifier);
4931 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004932 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004933 Index, Identifier, getContext().getRegisterInfo(), S,
4934 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004935 return MatchOperand_Success;
4936 }
4937
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004938 Index = matchHWRegsRegisterName(Identifier);
4939 if (Index != -1) {
4940 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004941 Index, Identifier, getContext().getRegisterInfo(), S,
4942 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004943 return MatchOperand_Success;
4944 }
4945
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004946 Index = matchFPURegisterName(Identifier);
4947 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004948 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004949 Index, Identifier, getContext().getRegisterInfo(), S,
4950 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004951 return MatchOperand_Success;
4952 }
4953
4954 Index = matchFCCRegisterName(Identifier);
4955 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004956 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004957 Index, Identifier, getContext().getRegisterInfo(), S,
4958 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004959 return MatchOperand_Success;
4960 }
4961
4962 Index = matchACRegisterName(Identifier);
4963 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004964 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004965 Index, Identifier, getContext().getRegisterInfo(), S,
4966 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004967 return MatchOperand_Success;
4968 }
4969
4970 Index = matchMSA128RegisterName(Identifier);
4971 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004972 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004973 Index, Identifier, getContext().getRegisterInfo(), S,
4974 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004975 return MatchOperand_Success;
4976 }
4977
4978 Index = matchMSA128CtrlRegisterName(Identifier);
4979 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004980 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004981 Index, Identifier, getContext().getRegisterInfo(), S,
4982 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004983 return MatchOperand_Success;
4984 }
4985
4986 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004987}
4988
Alex Bradbury58eba092016-11-01 16:32:05 +00004989OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004990MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004991 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004992 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004993
4994 if (Token.is(AsmToken::Identifier)) {
4995 DEBUG(dbgs() << ".. identifier\n");
4996 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004997 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004998 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004999 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005000 } else if (Token.is(AsmToken::Integer)) {
5001 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00005002 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005003 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
5004 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005005 return MatchOperand_Success;
5006 }
5007
5008 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
5009
5010 return MatchOperand_NoMatch;
5011}
5012
Alex Bradbury58eba092016-11-01 16:32:05 +00005013OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005014MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005015 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005016 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005017
5018 auto Token = Parser.getTok();
5019
5020 SMLoc S = Token.getLoc();
5021
5022 if (Token.isNot(AsmToken::Dollar)) {
5023 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
5024 if (Token.is(AsmToken::Identifier)) {
5025 if (searchSymbolAlias(Operands))
5026 return MatchOperand_Success;
5027 }
5028 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
5029 return MatchOperand_NoMatch;
5030 }
5031 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005032
Toma Tabacu13964452014-09-04 13:23:44 +00005033 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00005034 if (ResTy == MatchOperand_Success) {
5035 Parser.Lex(); // $
5036 Parser.Lex(); // identifier
5037 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005038 return ResTy;
5039}
5040
Alex Bradbury58eba092016-11-01 16:32:05 +00005041OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005042MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005043 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005044 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005045
5046 SMLoc S = getLexer().getLoc();
5047
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005048 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005049 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005050 if (ResTy != MatchOperand_NoMatch)
5051 return ResTy;
5052
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005053 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00005054 const MCExpr *Expr = nullptr;
5055 if (Parser.parseExpression(Expr)) {
5056 // We have no way of knowing if a symbol was consumed so we must ParseFail
5057 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005058 }
Daniel Sandersffd84362014-04-01 10:41:48 +00005059 Operands.push_back(
5060 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005061 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00005062}
5063
Alex Bradbury58eba092016-11-01 16:32:05 +00005064OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005065MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005066 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00005067 const MCExpr *IdVal;
5068 // If the first token is '$' we may have register operand.
5069 if (Parser.getTok().is(AsmToken::Dollar))
5070 return MatchOperand_NoMatch;
5071 SMLoc S = Parser.getTok().getLoc();
5072 if (getParser().parseExpression(IdVal))
5073 return MatchOperand_ParseFail;
5074 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00005075 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00005076 int64_t Val = MCE->getValue();
5077 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5078 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00005079 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00005080 return MatchOperand_Success;
5081}
5082
Alex Bradbury58eba092016-11-01 16:32:05 +00005083OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005084MipsAsmParser::parseRegisterList(OperandVector &Operands) {
5085 MCAsmParser &Parser = getParser();
5086 SmallVector<unsigned, 10> Regs;
5087 unsigned RegNo;
5088 unsigned PrevReg = Mips::NoRegister;
5089 bool RegRange = false;
5090 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5091
5092 if (Parser.getTok().isNot(AsmToken::Dollar))
5093 return MatchOperand_ParseFail;
5094
5095 SMLoc S = Parser.getTok().getLoc();
5096 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
5097 SMLoc E = getLexer().getLoc();
5098 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
5099 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
5100 if (RegRange) {
5101 // Remove last register operand because registers from register range
5102 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005103 if ((isGP64bit() && RegNo == Mips::RA_64) ||
5104 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005105 Regs.push_back(RegNo);
5106 } else {
5107 unsigned TmpReg = PrevReg + 1;
5108 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005109 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
5110 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
5111 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005112 Error(E, "invalid register operand");
5113 return MatchOperand_ParseFail;
5114 }
5115
5116 PrevReg = TmpReg;
5117 Regs.push_back(TmpReg++);
5118 }
5119 }
5120
5121 RegRange = false;
5122 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005123 if ((PrevReg == Mips::NoRegister) &&
5124 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
5125 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005126 Error(E, "$16 or $31 expected");
5127 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005128 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
5129 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
5130 !isGP64bit()) ||
5131 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
5132 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
5133 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005134 Error(E, "invalid register operand");
5135 return MatchOperand_ParseFail;
5136 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005137 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
5138 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
5139 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005140 Error(E, "consecutive register numbers expected");
5141 return MatchOperand_ParseFail;
5142 }
5143
5144 Regs.push_back(RegNo);
5145 }
5146
5147 if (Parser.getTok().is(AsmToken::Minus))
5148 RegRange = true;
5149
5150 if (!Parser.getTok().isNot(AsmToken::Minus) &&
5151 !Parser.getTok().isNot(AsmToken::Comma)) {
5152 Error(E, "',' or '-' expected");
5153 return MatchOperand_ParseFail;
5154 }
5155
5156 Lex(); // Consume comma or minus
5157 if (Parser.getTok().isNot(AsmToken::Dollar))
5158 break;
5159
5160 PrevReg = RegNo;
5161 }
5162
5163 SMLoc E = Parser.getTok().getLoc();
5164 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5165 parseMemOperand(Operands);
5166 return MatchOperand_Success;
5167}
5168
Alex Bradbury58eba092016-11-01 16:32:05 +00005169OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005170MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
5171 MCAsmParser &Parser = getParser();
5172
5173 SMLoc S = Parser.getTok().getLoc();
5174 if (parseAnyRegister(Operands) != MatchOperand_Success)
5175 return MatchOperand_ParseFail;
5176
5177 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00005178 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00005179
Benjamin Kramer2b68d152016-05-09 10:31:17 +00005180 Operands.pop_back();
5181 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005182 return MatchOperand_Success;
5183}
5184
Alex Bradbury58eba092016-11-01 16:32:05 +00005185OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00005186MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
5187 MCAsmParser &Parser = getParser();
5188 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5189 SmallVector<unsigned, 10> Regs;
5190
5191 if (Parser.getTok().isNot(AsmToken::Dollar))
5192 return MatchOperand_ParseFail;
5193
5194 SMLoc S = Parser.getTok().getLoc();
5195
5196 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5197 return MatchOperand_ParseFail;
5198
5199 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5200 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5201 Regs.push_back(RegNo);
5202
5203 SMLoc E = Parser.getTok().getLoc();
5204 if (Parser.getTok().isNot(AsmToken::Comma)) {
5205 Error(E, "',' expected");
5206 return MatchOperand_ParseFail;
5207 }
5208
5209 // Remove comma.
5210 Parser.Lex();
5211
5212 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5213 return MatchOperand_ParseFail;
5214
5215 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5216 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5217 Regs.push_back(RegNo);
5218
5219 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5220
5221 return MatchOperand_Success;
5222}
5223
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005224/// Sometimes (i.e. load/stores) the operand may be followed immediately by
5225/// either this.
5226/// ::= '(', register, ')'
5227/// handle it before we iterate so we don't get tripped up by the lack of
5228/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005229bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005230 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005231 if (getLexer().is(AsmToken::LParen)) {
5232 Operands.push_back(
5233 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
5234 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005235 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005236 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005237 return Error(Loc, "unexpected token in argument list");
5238 }
5239 if (Parser.getTok().isNot(AsmToken::RParen)) {
5240 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005241 return Error(Loc, "unexpected token, expected ')'");
5242 }
5243 Operands.push_back(
5244 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
5245 Parser.Lex();
5246 }
5247 return false;
5248}
5249
5250/// Sometimes (i.e. in MSA) the operand may be followed immediately by
5251/// either one of these.
5252/// ::= '[', register, ']'
5253/// ::= '[', integer, ']'
5254/// handle it before we iterate so we don't get tripped up by the lack of
5255/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005256bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00005257 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005258 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005259 if (getLexer().is(AsmToken::LBrac)) {
5260 Operands.push_back(
5261 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
5262 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005263 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005264 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005265 return Error(Loc, "unexpected token in argument list");
5266 }
5267 if (Parser.getTok().isNot(AsmToken::RBrac)) {
5268 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005269 return Error(Loc, "unexpected token, expected ']'");
5270 }
5271 Operands.push_back(
5272 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
5273 Parser.Lex();
5274 }
5275 return false;
5276}
5277
David Blaikie960ea3f2014-06-08 16:18:35 +00005278bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
5279 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005280 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005281 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005282
5283 // We have reached first instruction, module directive are now forbidden.
5284 getTargetStreamer().forbidModuleDirective();
5285
Vladimir Medic74593e62013-07-17 15:00:42 +00005286 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00005287 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005288 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00005289 }
Vladimir Medic64828a12013-07-16 10:07:14 +00005290 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005291 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005292
5293 // Read the remaining operands.
5294 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5295 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005296 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005297 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005298 return Error(Loc, "unexpected token in argument list");
5299 }
Toma Tabacu13964452014-09-04 13:23:44 +00005300 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005301 return true;
5302 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00005303
Jack Carterd0bd6422013-04-18 00:41:53 +00005304 while (getLexer().is(AsmToken::Comma)) {
5305 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00005306 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005307 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005308 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005309 return Error(Loc, "unexpected token in argument list");
5310 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005311 // Parse bracket and parenthesis suffixes before we iterate
5312 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00005313 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005314 return true;
5315 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00005316 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005317 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005318 }
5319 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005320 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5321 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005322 return Error(Loc, "unexpected token in argument list");
5323 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005324 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00005325 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00005326}
5327
Nirav Dave996fc132016-05-05 14:15:46 +00005328// FIXME: Given that these have the same name, these should both be
5329// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005330bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005331 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005332 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00005333}
5334
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005335bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005336 return Error(Loc, ErrorMsg);
5337}
5338
Jack Carter0b744b32012-10-04 02:29:46 +00005339bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005340 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005341 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00005342
5343 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00005344 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00005345
5346 Parser.Lex(); // Eat "noat".
5347
Jack Carterd0bd6422013-04-18 00:41:53 +00005348 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005349 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005350 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005351 return false;
5352 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005353
5354 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005355 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005356 return false;
5357}
Jack Carterd0bd6422013-04-18 00:41:53 +00005358
Jack Carter0b744b32012-10-04 02:29:46 +00005359bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00005360 // Line can be: ".set at", which sets $at to $1
5361 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00005362 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00005363 Parser.Lex(); // Eat "at".
5364
Jack Carter0b744b32012-10-04 02:29:46 +00005365 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005366 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00005367 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00005368
5369 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005370 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005371 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00005372 }
5373
5374 if (getLexer().isNot(AsmToken::Equal)) {
5375 reportParseError("unexpected token, expected equals sign");
5376 return false;
5377 }
5378 Parser.Lex(); // Eat "=".
5379
5380 if (getLexer().isNot(AsmToken::Dollar)) {
5381 if (getLexer().is(AsmToken::EndOfStatement)) {
5382 reportParseError("no register specified");
5383 return false;
5384 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00005385 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00005386 return false;
5387 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005388 }
5389 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00005390
Toma Tabacu16a74492015-02-13 10:30:57 +00005391 // Find out what "reg" is.
5392 unsigned AtRegNo;
5393 const AsmToken &Reg = Parser.getTok();
5394 if (Reg.is(AsmToken::Identifier)) {
5395 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
5396 } else if (Reg.is(AsmToken::Integer)) {
5397 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00005398 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00005399 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00005400 return false;
5401 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005402
5403 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00005404 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005405 reportParseError("invalid register");
5406 return false;
5407 }
5408 Parser.Lex(); // Eat "reg".
5409
5410 // If this is not the end of the statement, report an error.
5411 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5412 reportParseError("unexpected token, expected end of statement");
5413 return false;
5414 }
5415
5416 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
5417
5418 Parser.Lex(); // Consume the EndOfStatement.
5419 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005420}
5421
5422bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005423 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005424 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005425 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005426 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005427 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005428 return false;
5429 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005430 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00005431 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005432 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005433 return false;
5434}
5435
5436bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005437 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005438 Parser.Lex();
5439 // If this is not the end of the statement, report an error.
5440 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005441 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005442 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005443 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005444 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005445 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005446 Parser.Lex(); // Consume the EndOfStatement.
5447 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005448}
5449
5450bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005451 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005452 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005453 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005454 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005455 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005456 return false;
5457 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005458 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005459 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005460 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005461 return false;
5462}
5463
5464bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005465 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005466 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005467 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005468 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005469 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005470 return false;
5471 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005472 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005473 reportParseError("`noreorder' must be set before `nomacro'");
5474 return false;
5475 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005476 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005477 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005478 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005479 return false;
5480}
Jack Carterd76b2372013-03-21 21:44:16 +00005481
Daniel Sanders44934432014-08-07 12:03:36 +00005482bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005483 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005484 Parser.Lex();
5485
5486 // If this is not the end of the statement, report an error.
5487 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005488 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005489
5490 setFeatureBits(Mips::FeatureMSA, "msa");
5491 getTargetStreamer().emitDirectiveSetMsa();
5492 return false;
5493}
5494
5495bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005496 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005497 Parser.Lex();
5498
5499 // If this is not the end of the statement, report an error.
5500 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005501 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005502
5503 clearFeatureBits(Mips::FeatureMSA, "msa");
5504 getTargetStreamer().emitDirectiveSetNoMsa();
5505 return false;
5506}
5507
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005508bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005509 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005510 Parser.Lex(); // Eat "nodsp".
5511
5512 // If this is not the end of the statement, report an error.
5513 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5514 reportParseError("unexpected token, expected end of statement");
5515 return false;
5516 }
5517
5518 clearFeatureBits(Mips::FeatureDSP, "dsp");
5519 getTargetStreamer().emitDirectiveSetNoDsp();
5520 return false;
5521}
5522
Toma Tabacucc2502d2014-11-04 17:18:07 +00005523bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005524 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005525 Parser.Lex(); // Eat "mips16".
5526
Jack Carter39536722014-01-22 23:08:42 +00005527 // If this is not the end of the statement, report an error.
5528 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005529 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005530 return false;
5531 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005532
5533 setFeatureBits(Mips::FeatureMips16, "mips16");
5534 getTargetStreamer().emitDirectiveSetMips16();
5535 Parser.Lex(); // Consume the EndOfStatement.
5536 return false;
5537}
5538
5539bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005540 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005541 Parser.Lex(); // Eat "nomips16".
5542
5543 // If this is not the end of the statement, report an error.
5544 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5545 reportParseError("unexpected token, expected end of statement");
5546 return false;
5547 }
5548
5549 clearFeatureBits(Mips::FeatureMips16, "mips16");
5550 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005551 Parser.Lex(); // Consume the EndOfStatement.
5552 return false;
5553}
5554
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005555bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005556 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005557 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005558 // Line can be: .set fp=32
5559 // .set fp=xx
5560 // .set fp=64
5561 Parser.Lex(); // Eat fp token
5562 AsmToken Tok = Parser.getTok();
5563 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005564 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005565 return false;
5566 }
5567 Parser.Lex(); // Eat '=' token.
5568 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005569
5570 if (!parseFpABIValue(FpAbiVal, ".set"))
5571 return false;
5572
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005573 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005574 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005575 return false;
5576 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005577 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005578 Parser.Lex(); // Consume the EndOfStatement.
5579 return false;
5580}
5581
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005582bool MipsAsmParser::parseSetOddSPRegDirective() {
5583 MCAsmParser &Parser = getParser();
5584
5585 Parser.Lex(); // Eat "oddspreg".
5586 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5587 reportParseError("unexpected token, expected end of statement");
5588 return false;
5589 }
5590
5591 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5592 getTargetStreamer().emitDirectiveSetOddSPReg();
5593 return false;
5594}
5595
5596bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5597 MCAsmParser &Parser = getParser();
5598
5599 Parser.Lex(); // Eat "nooddspreg".
5600 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5601 reportParseError("unexpected token, expected end of statement");
5602 return false;
5603 }
5604
5605 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5606 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5607 return false;
5608}
5609
Toma Tabacu9db22db2014-09-09 10:15:38 +00005610bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005611 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005612 SMLoc Loc = getLexer().getLoc();
5613
5614 Parser.Lex();
5615 if (getLexer().isNot(AsmToken::EndOfStatement))
5616 return reportParseError("unexpected token, expected end of statement");
5617
5618 // Always keep an element on the options "stack" to prevent the user
5619 // from changing the initial options. This is how we remember them.
5620 if (AssemblerOptions.size() == 2)
5621 return reportParseError(Loc, ".set pop with no .set push");
5622
Akira Hatanakab11ef082015-11-14 06:35:56 +00005623 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005624 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005625 setAvailableFeatures(
5626 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5627 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005628
5629 getTargetStreamer().emitDirectiveSetPop();
5630 return false;
5631}
5632
5633bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005634 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005635 Parser.Lex();
5636 if (getLexer().isNot(AsmToken::EndOfStatement))
5637 return reportParseError("unexpected token, expected end of statement");
5638
5639 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005640 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005641 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005642
5643 getTargetStreamer().emitDirectiveSetPush();
5644 return false;
5645}
5646
Toma Tabacu29696502015-06-02 09:48:04 +00005647bool MipsAsmParser::parseSetSoftFloatDirective() {
5648 MCAsmParser &Parser = getParser();
5649 Parser.Lex();
5650 if (getLexer().isNot(AsmToken::EndOfStatement))
5651 return reportParseError("unexpected token, expected end of statement");
5652
5653 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5654 getTargetStreamer().emitDirectiveSetSoftFloat();
5655 return false;
5656}
5657
5658bool MipsAsmParser::parseSetHardFloatDirective() {
5659 MCAsmParser &Parser = getParser();
5660 Parser.Lex();
5661 if (getLexer().isNot(AsmToken::EndOfStatement))
5662 return reportParseError("unexpected token, expected end of statement");
5663
5664 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5665 getTargetStreamer().emitDirectiveSetHardFloat();
5666 return false;
5667}
5668
Jack Carterd76b2372013-03-21 21:44:16 +00005669bool MipsAsmParser::parseSetAssignment() {
5670 StringRef Name;
5671 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005672 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005673
5674 if (Parser.parseIdentifier(Name))
5675 reportParseError("expected identifier after .set");
5676
5677 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005678 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005679 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005680
Jack Carter3b2c96e2014-01-22 23:31:38 +00005681 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005682 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005683
Jim Grosbach6f482002015-05-18 18:43:14 +00005684 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005685 Sym->setVariableValue(Value);
5686
5687 return false;
5688}
Jack Carterd0bd6422013-04-18 00:41:53 +00005689
Toma Tabacu26647792014-09-09 12:52:14 +00005690bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005691 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005692 Parser.Lex();
5693 if (getLexer().isNot(AsmToken::EndOfStatement))
5694 return reportParseError("unexpected token, expected end of statement");
5695
5696 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005697 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005698 setAvailableFeatures(
5699 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5700 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005701 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5702
5703 getTargetStreamer().emitDirectiveSetMips0();
5704 return false;
5705}
5706
Toma Tabacu85618b32014-08-19 14:22:52 +00005707bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005708 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005709 Parser.Lex();
5710 if (getLexer().isNot(AsmToken::Equal))
5711 return reportParseError("unexpected token, expected equals sign");
5712
5713 Parser.Lex();
5714 StringRef Arch;
5715 if (Parser.parseIdentifier(Arch))
5716 return reportParseError("expected arch identifier");
5717
5718 StringRef ArchFeatureName =
5719 StringSwitch<StringRef>(Arch)
5720 .Case("mips1", "mips1")
5721 .Case("mips2", "mips2")
5722 .Case("mips3", "mips3")
5723 .Case("mips4", "mips4")
5724 .Case("mips5", "mips5")
5725 .Case("mips32", "mips32")
5726 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005727 .Case("mips32r3", "mips32r3")
5728 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005729 .Case("mips32r6", "mips32r6")
5730 .Case("mips64", "mips64")
5731 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005732 .Case("mips64r3", "mips64r3")
5733 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005734 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005735 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005736 .Case("r4000", "mips3") // This is an implementation of Mips3.
5737 .Default("");
5738
5739 if (ArchFeatureName.empty())
5740 return reportParseError("unsupported architecture");
5741
5742 selectArch(ArchFeatureName);
5743 getTargetStreamer().emitDirectiveSetArch(Arch);
5744 return false;
5745}
5746
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005747bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005748 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005749 Parser.Lex();
5750 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005751 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005752
Matheus Almeida2852af82014-04-22 10:15:54 +00005753 switch (Feature) {
5754 default:
5755 llvm_unreachable("Unimplemented feature");
5756 case Mips::FeatureDSP:
5757 setFeatureBits(Mips::FeatureDSP, "dsp");
5758 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005759 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005760 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00005761 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00005762 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005763 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005764 case Mips::FeatureMips1:
5765 selectArch("mips1");
5766 getTargetStreamer().emitDirectiveSetMips1();
5767 break;
5768 case Mips::FeatureMips2:
5769 selectArch("mips2");
5770 getTargetStreamer().emitDirectiveSetMips2();
5771 break;
5772 case Mips::FeatureMips3:
5773 selectArch("mips3");
5774 getTargetStreamer().emitDirectiveSetMips3();
5775 break;
5776 case Mips::FeatureMips4:
5777 selectArch("mips4");
5778 getTargetStreamer().emitDirectiveSetMips4();
5779 break;
5780 case Mips::FeatureMips5:
5781 selectArch("mips5");
5782 getTargetStreamer().emitDirectiveSetMips5();
5783 break;
5784 case Mips::FeatureMips32:
5785 selectArch("mips32");
5786 getTargetStreamer().emitDirectiveSetMips32();
5787 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005788 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005789 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005790 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005791 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005792 case Mips::FeatureMips32r3:
5793 selectArch("mips32r3");
5794 getTargetStreamer().emitDirectiveSetMips32R3();
5795 break;
5796 case Mips::FeatureMips32r5:
5797 selectArch("mips32r5");
5798 getTargetStreamer().emitDirectiveSetMips32R5();
5799 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005800 case Mips::FeatureMips32r6:
5801 selectArch("mips32r6");
5802 getTargetStreamer().emitDirectiveSetMips32R6();
5803 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005804 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005805 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005806 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005807 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005808 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005809 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005810 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005811 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005812 case Mips::FeatureMips64r3:
5813 selectArch("mips64r3");
5814 getTargetStreamer().emitDirectiveSetMips64R3();
5815 break;
5816 case Mips::FeatureMips64r5:
5817 selectArch("mips64r5");
5818 getTargetStreamer().emitDirectiveSetMips64R5();
5819 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005820 case Mips::FeatureMips64r6:
5821 selectArch("mips64r6");
5822 getTargetStreamer().emitDirectiveSetMips64R6();
5823 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005824 }
5825 return false;
5826}
5827
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005828bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005829 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005830 if (getLexer().isNot(AsmToken::Comma)) {
5831 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005832 return Error(Loc, ErrorStr);
5833 }
5834
Matheus Almeida2852af82014-04-22 10:15:54 +00005835 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005836 return true;
5837}
5838
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005839// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5840// In this class, it is only used for .cprestore.
5841// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5842// MipsTargetELFStreamer and MipsAsmParser.
5843bool MipsAsmParser::isPicAndNotNxxAbi() {
5844 return inPicMode() && !(isABI_N32() || isABI_N64());
5845}
5846
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005847bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005848 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005849 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005850
Toma Tabacudde4c462014-11-06 10:02:45 +00005851 if (inMips16Mode()) {
5852 reportParseError(".cpload is not supported in Mips16 mode");
5853 return false;
5854 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005855
David Blaikie960ea3f2014-06-08 16:18:35 +00005856 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005857 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005858 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5859 reportParseError("expected register containing function address");
5860 return false;
5861 }
5862
David Blaikie960ea3f2014-06-08 16:18:35 +00005863 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5864 if (!RegOpnd.isGPRAsmReg()) {
5865 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005866 return false;
5867 }
5868
Toma Tabacudde4c462014-11-06 10:02:45 +00005869 // If this is not the end of the statement, report an error.
5870 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5871 reportParseError("unexpected token, expected end of statement");
5872 return false;
5873 }
5874
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005875 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005876 return false;
5877}
5878
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005879bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5880 MCAsmParser &Parser = getParser();
5881
5882 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5883 // is used in non-PIC mode.
5884
5885 if (inMips16Mode()) {
5886 reportParseError(".cprestore is not supported in Mips16 mode");
5887 return false;
5888 }
5889
5890 // Get the stack offset value.
5891 const MCExpr *StackOffset;
5892 int64_t StackOffsetVal;
5893 if (Parser.parseExpression(StackOffset)) {
5894 reportParseError("expected stack offset value");
5895 return false;
5896 }
5897
5898 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5899 reportParseError("stack offset is not an absolute expression");
5900 return false;
5901 }
5902
5903 if (StackOffsetVal < 0) {
5904 Warning(Loc, ".cprestore with negative stack offset has no effect");
5905 IsCpRestoreSet = false;
5906 } else {
5907 IsCpRestoreSet = true;
5908 CpRestoreOffset = StackOffsetVal;
5909 }
5910
5911 // If this is not the end of the statement, report an error.
5912 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5913 reportParseError("unexpected token, expected end of statement");
5914 return false;
5915 }
5916
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005917 if (!getTargetStreamer().emitDirectiveCpRestore(
5918 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005919 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005920 Parser.Lex(); // Consume the EndOfStatement.
5921 return false;
5922}
5923
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005924bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005925 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005926 unsigned FuncReg;
5927 unsigned Save;
5928 bool SaveIsReg = true;
5929
Matheus Almeida7e815762014-06-18 13:08:59 +00005930 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005931 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005932 if (ResTy == MatchOperand_NoMatch) {
5933 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005934 return false;
5935 }
5936
5937 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5938 if (!FuncRegOpnd.isGPRAsmReg()) {
5939 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005940 return false;
5941 }
5942
5943 FuncReg = FuncRegOpnd.getGPR32Reg();
5944 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005945
Toma Tabacu65f10572014-09-16 15:00:52 +00005946 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005947 return true;
5948
Toma Tabacu13964452014-09-04 13:23:44 +00005949 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005950 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005951 const MCExpr *OffsetExpr;
5952 int64_t OffsetVal;
5953 SMLoc ExprLoc = getLexer().getLoc();
5954
5955 if (Parser.parseExpression(OffsetExpr) ||
5956 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5957 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005958 return false;
5959 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005960
5961 Save = OffsetVal;
5962 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005963 } else {
5964 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5965 if (!SaveOpnd.isGPRAsmReg()) {
5966 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005967 return false;
5968 }
5969 Save = SaveOpnd.getGPR32Reg();
5970 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005971
Toma Tabacu65f10572014-09-16 15:00:52 +00005972 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005973 return true;
5974
Toma Tabacu8874eac2015-02-18 13:46:53 +00005975 const MCExpr *Expr;
5976 if (Parser.parseExpression(Expr)) {
5977 reportParseError("expected expression");
5978 return false;
5979 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005980
Toma Tabacu8874eac2015-02-18 13:46:53 +00005981 if (Expr->getKind() != MCExpr::SymbolRef) {
5982 reportParseError("expected symbol");
5983 return false;
5984 }
5985 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5986
Daniel Sandersf173dda2015-09-22 10:50:09 +00005987 CpSaveLocation = Save;
5988 CpSaveLocationIsRegister = SaveIsReg;
5989
Toma Tabacu8874eac2015-02-18 13:46:53 +00005990 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5991 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005992 return false;
5993}
5994
Daniel Sandersf173dda2015-09-22 10:50:09 +00005995bool MipsAsmParser::parseDirectiveCPReturn() {
5996 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5997 CpSaveLocationIsRegister);
5998 return false;
5999}
6000
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006001bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006002 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006003 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6004 const AsmToken &Tok = Parser.getTok();
6005
6006 if (Tok.getString() == "2008") {
6007 Parser.Lex();
6008 getTargetStreamer().emitDirectiveNaN2008();
6009 return false;
6010 } else if (Tok.getString() == "legacy") {
6011 Parser.Lex();
6012 getTargetStreamer().emitDirectiveNaNLegacy();
6013 return false;
6014 }
6015 }
6016 // If we don't recognize the option passed to the .nan
6017 // directive (e.g. no option or unknown option), emit an error.
6018 reportParseError("invalid option in .nan directive");
6019 return false;
6020}
6021
Jack Carter0b744b32012-10-04 02:29:46 +00006022bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006023 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006024 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00006025 const AsmToken &Tok = Parser.getTok();
6026
6027 if (Tok.getString() == "noat") {
6028 return parseSetNoAtDirective();
6029 } else if (Tok.getString() == "at") {
6030 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00006031 } else if (Tok.getString() == "arch") {
6032 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006033 } else if (Tok.getString() == "fp") {
6034 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006035 } else if (Tok.getString() == "oddspreg") {
6036 return parseSetOddSPRegDirective();
6037 } else if (Tok.getString() == "nooddspreg") {
6038 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006039 } else if (Tok.getString() == "pop") {
6040 return parseSetPopDirective();
6041 } else if (Tok.getString() == "push") {
6042 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00006043 } else if (Tok.getString() == "reorder") {
6044 return parseSetReorderDirective();
6045 } else if (Tok.getString() == "noreorder") {
6046 return parseSetNoReorderDirective();
6047 } else if (Tok.getString() == "macro") {
6048 return parseSetMacroDirective();
6049 } else if (Tok.getString() == "nomacro") {
6050 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00006051 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00006052 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006053 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00006054 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006055 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00006056 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00006057 getTargetStreamer().emitDirectiveSetNoMicroMips();
6058 Parser.eatToEndOfStatement();
6059 return false;
6060 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006061 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00006062 } else if (Tok.getString() == "mips0") {
6063 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00006064 } else if (Tok.getString() == "mips1") {
6065 return parseSetFeature(Mips::FeatureMips1);
6066 } else if (Tok.getString() == "mips2") {
6067 return parseSetFeature(Mips::FeatureMips2);
6068 } else if (Tok.getString() == "mips3") {
6069 return parseSetFeature(Mips::FeatureMips3);
6070 } else if (Tok.getString() == "mips4") {
6071 return parseSetFeature(Mips::FeatureMips4);
6072 } else if (Tok.getString() == "mips5") {
6073 return parseSetFeature(Mips::FeatureMips5);
6074 } else if (Tok.getString() == "mips32") {
6075 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00006076 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006077 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006078 } else if (Tok.getString() == "mips32r3") {
6079 return parseSetFeature(Mips::FeatureMips32r3);
6080 } else if (Tok.getString() == "mips32r5") {
6081 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006082 } else if (Tok.getString() == "mips32r6") {
6083 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006084 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006085 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006086 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006087 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006088 } else if (Tok.getString() == "mips64r3") {
6089 return parseSetFeature(Mips::FeatureMips64r3);
6090 } else if (Tok.getString() == "mips64r5") {
6091 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006092 } else if (Tok.getString() == "mips64r6") {
6093 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00006094 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006095 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006096 } else if (Tok.getString() == "nodsp") {
6097 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00006098 } else if (Tok.getString() == "msa") {
6099 return parseSetMsaDirective();
6100 } else if (Tok.getString() == "nomsa") {
6101 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00006102 } else if (Tok.getString() == "softfloat") {
6103 return parseSetSoftFloatDirective();
6104 } else if (Tok.getString() == "hardfloat") {
6105 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00006106 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00006107 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00006108 parseSetAssignment();
6109 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006110 }
Jack Carter07c818d2013-01-25 01:31:34 +00006111
Jack Carter0b744b32012-10-04 02:29:46 +00006112 return true;
6113}
6114
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006115/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00006116/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006117bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006118 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006119 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006120 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00006121 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00006122 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00006123 return true;
6124
6125 getParser().getStreamer().EmitValue(Value, Size);
6126
6127 if (getLexer().is(AsmToken::EndOfStatement))
6128 break;
6129
Jack Carter07c818d2013-01-25 01:31:34 +00006130 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006131 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00006132 Parser.Lex();
6133 }
6134 }
6135
6136 Parser.Lex();
6137 return false;
6138}
6139
Vladimir Medic4c299852013-11-06 11:27:05 +00006140/// parseDirectiveGpWord
6141/// ::= .gpword local_sym
6142bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006143 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00006144 const MCExpr *Value;
6145 // EmitGPRel32Value requires an expression, so we are using base class
6146 // method to evaluate the expression.
6147 if (getParser().parseExpression(Value))
6148 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00006149 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00006150
Vladimir Medice10c1122013-11-13 13:18:04 +00006151 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006152 return Error(getLexer().getLoc(),
6153 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00006154 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00006155 return false;
6156}
6157
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006158/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00006159/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006160bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006161 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006162 const MCExpr *Value;
6163 // EmitGPRel64Value requires an expression, so we are using base class
6164 // method to evaluate the expression.
6165 if (getParser().parseExpression(Value))
6166 return true;
6167 getParser().getStreamer().EmitGPRel64Value(Value);
6168
6169 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006170 return Error(getLexer().getLoc(),
6171 "unexpected token, expected end of statement");
6172 Parser.Lex(); // Eat EndOfStatement token.
6173 return false;
6174}
6175
6176/// parseDirectiveDtpRelWord
6177/// ::= .dtprelword tls_sym
6178bool MipsAsmParser::parseDirectiveDtpRelWord() {
6179 MCAsmParser &Parser = getParser();
6180 const MCExpr *Value;
6181 // EmitDTPRel32Value requires an expression, so we are using base class
6182 // method to evaluate the expression.
6183 if (getParser().parseExpression(Value))
6184 return true;
6185 getParser().getStreamer().EmitDTPRel32Value(Value);
6186
6187 if (getLexer().isNot(AsmToken::EndOfStatement))
6188 return Error(getLexer().getLoc(),
6189 "unexpected token, expected end of statement");
6190 Parser.Lex(); // Eat EndOfStatement token.
6191 return false;
6192}
6193
6194/// parseDirectiveDtpRelDWord
6195/// ::= .dtpreldword tls_sym
6196bool MipsAsmParser::parseDirectiveDtpRelDWord() {
6197 MCAsmParser &Parser = getParser();
6198 const MCExpr *Value;
6199 // EmitDTPRel64Value requires an expression, so we are using base class
6200 // method to evaluate the expression.
6201 if (getParser().parseExpression(Value))
6202 return true;
6203 getParser().getStreamer().EmitDTPRel64Value(Value);
6204
6205 if (getLexer().isNot(AsmToken::EndOfStatement))
6206 return Error(getLexer().getLoc(),
6207 "unexpected token, expected end of statement");
6208 Parser.Lex(); // Eat EndOfStatement token.
6209 return false;
6210}
6211
6212/// parseDirectiveTpRelWord
6213/// ::= .tprelword tls_sym
6214bool MipsAsmParser::parseDirectiveTpRelWord() {
6215 MCAsmParser &Parser = getParser();
6216 const MCExpr *Value;
6217 // EmitTPRel32Value requires an expression, so we are using base class
6218 // method to evaluate the expression.
6219 if (getParser().parseExpression(Value))
6220 return true;
6221 getParser().getStreamer().EmitTPRel32Value(Value);
6222
6223 if (getLexer().isNot(AsmToken::EndOfStatement))
6224 return Error(getLexer().getLoc(),
6225 "unexpected token, expected end of statement");
6226 Parser.Lex(); // Eat EndOfStatement token.
6227 return false;
6228}
6229
6230/// parseDirectiveTpRelDWord
6231/// ::= .tpreldword tls_sym
6232bool MipsAsmParser::parseDirectiveTpRelDWord() {
6233 MCAsmParser &Parser = getParser();
6234 const MCExpr *Value;
6235 // EmitTPRel64Value requires an expression, so we are using base class
6236 // method to evaluate the expression.
6237 if (getParser().parseExpression(Value))
6238 return true;
6239 getParser().getStreamer().EmitTPRel64Value(Value);
6240
6241 if (getLexer().isNot(AsmToken::EndOfStatement))
6242 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00006243 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00006244 Parser.Lex(); // Eat EndOfStatement token.
6245 return false;
6246}
6247
Jack Carter0cd3c192014-01-06 23:27:31 +00006248bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006249 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00006250 // Get the option token.
6251 AsmToken Tok = Parser.getTok();
6252 // At the moment only identifiers are supported.
6253 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006254 return Error(Parser.getTok().getLoc(),
6255 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00006256 }
6257
6258 StringRef Option = Tok.getIdentifier();
6259
6260 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006261 // MipsAsmParser needs to know if the current PIC mode changes.
6262 IsPicEnabled = false;
6263
Jack Carter0cd3c192014-01-06 23:27:31 +00006264 getTargetStreamer().emitDirectiveOptionPic0();
6265 Parser.Lex();
6266 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006267 return Error(Parser.getTok().getLoc(),
6268 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006269 }
6270 return false;
6271 }
6272
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006273 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006274 // MipsAsmParser needs to know if the current PIC mode changes.
6275 IsPicEnabled = true;
6276
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006277 getTargetStreamer().emitDirectiveOptionPic2();
6278 Parser.Lex();
6279 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006280 return Error(Parser.getTok().getLoc(),
6281 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006282 }
6283 return false;
6284 }
6285
Jack Carter0cd3c192014-01-06 23:27:31 +00006286 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00006287 Warning(Parser.getTok().getLoc(),
6288 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00006289 Parser.eatToEndOfStatement();
6290 return false;
6291}
6292
Toma Tabacu9ca50962015-04-16 09:53:47 +00006293/// parseInsnDirective
6294/// ::= .insn
6295bool MipsAsmParser::parseInsnDirective() {
6296 // If this is not the end of the statement, report an error.
6297 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6298 reportParseError("unexpected token, expected end of statement");
6299 return false;
6300 }
6301
6302 // The actual label marking happens in
6303 // MipsELFStreamer::createPendingLabelRelocs().
6304 getTargetStreamer().emitDirectiveInsn();
6305
6306 getParser().Lex(); // Eat EndOfStatement token.
6307 return false;
6308}
6309
Simon Atanasyanbe186202016-02-11 06:45:54 +00006310/// parseSSectionDirective
6311/// ::= .sbss
6312/// ::= .sdata
6313bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
6314 // If this is not the end of the statement, report an error.
6315 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6316 reportParseError("unexpected token, expected end of statement");
6317 return false;
6318 }
6319
6320 MCSection *ELFSection = getContext().getELFSection(
6321 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
6322 getParser().getStreamer().SwitchSection(ELFSection);
6323
6324 getParser().Lex(); // Eat EndOfStatement token.
6325 return false;
6326}
6327
Daniel Sanders7e527422014-07-10 13:38:23 +00006328/// parseDirectiveModule
6329/// ::= .module oddspreg
6330/// ::= .module nooddspreg
6331/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00006332/// ::= .module softfloat
6333/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006334bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006335 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006336 MCAsmLexer &Lexer = getLexer();
6337 SMLoc L = Lexer.getLoc();
6338
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006339 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006340 // TODO : get a better message.
6341 reportParseError(".module directive must appear before any code");
6342 return false;
6343 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006344
Toma Tabacuc405c822015-01-23 10:40:19 +00006345 StringRef Option;
6346 if (Parser.parseIdentifier(Option)) {
6347 reportParseError("expected .module option identifier");
6348 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006349 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006350
Toma Tabacuc405c822015-01-23 10:40:19 +00006351 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006352 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006353
Toma Tabacu3c499582015-06-25 10:56:57 +00006354 // Synchronize the abiflags information with the FeatureBits information we
6355 // changed above.
6356 getTargetStreamer().updateABIInfo(*this);
6357
6358 // If printing assembly, use the recently updated abiflags information.
6359 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6360 // emitted at the end).
6361 getTargetStreamer().emitDirectiveModuleOddSPReg();
6362
Toma Tabacuc405c822015-01-23 10:40:19 +00006363 // If this is not the end of the statement, report an error.
6364 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6365 reportParseError("unexpected token, expected end of statement");
6366 return false;
6367 }
6368
6369 return false; // parseDirectiveModule has finished successfully.
6370 } else if (Option == "nooddspreg") {
6371 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006372 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00006373 }
6374
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006375 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006376
Toma Tabacu3c499582015-06-25 10:56:57 +00006377 // Synchronize the abiflags information with the FeatureBits information we
6378 // changed above.
6379 getTargetStreamer().updateABIInfo(*this);
6380
6381 // If printing assembly, use the recently updated abiflags information.
6382 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6383 // emitted at the end).
6384 getTargetStreamer().emitDirectiveModuleOddSPReg();
6385
Toma Tabacuc405c822015-01-23 10:40:19 +00006386 // If this is not the end of the statement, report an error.
6387 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6388 reportParseError("unexpected token, expected end of statement");
6389 return false;
6390 }
6391
6392 return false; // parseDirectiveModule has finished successfully.
6393 } else if (Option == "fp") {
6394 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00006395 } else if (Option == "softfloat") {
6396 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6397
6398 // Synchronize the ABI Flags information with the FeatureBits information we
6399 // updated above.
6400 getTargetStreamer().updateABIInfo(*this);
6401
6402 // If printing assembly, use the recently updated ABI Flags information.
6403 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6404 // emitted later).
6405 getTargetStreamer().emitDirectiveModuleSoftFloat();
6406
6407 // If this is not the end of the statement, report an error.
6408 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6409 reportParseError("unexpected token, expected end of statement");
6410 return false;
6411 }
6412
6413 return false; // parseDirectiveModule has finished successfully.
6414 } else if (Option == "hardfloat") {
6415 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6416
6417 // Synchronize the ABI Flags information with the FeatureBits information we
6418 // updated above.
6419 getTargetStreamer().updateABIInfo(*this);
6420
6421 // If printing assembly, use the recently updated ABI Flags information.
6422 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6423 // emitted later).
6424 getTargetStreamer().emitDirectiveModuleHardFloat();
6425
6426 // If this is not the end of the statement, report an error.
6427 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6428 reportParseError("unexpected token, expected end of statement");
6429 return false;
6430 }
6431
6432 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00006433 } else {
6434 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
6435 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006436}
6437
6438/// parseDirectiveModuleFP
6439/// ::= =32
6440/// ::= =xx
6441/// ::= =64
6442bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006443 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006444 MCAsmLexer &Lexer = getLexer();
6445
6446 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006447 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006448 return false;
6449 }
6450 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006451
Daniel Sanders7e527422014-07-10 13:38:23 +00006452 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006453 if (!parseFpABIValue(FpABI, ".module"))
6454 return false;
6455
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006456 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006457 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006458 return false;
6459 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006460
Toma Tabacua64e5402015-06-25 12:44:38 +00006461 // Synchronize the abiflags information with the FeatureBits information we
6462 // changed above.
6463 getTargetStreamer().updateABIInfo(*this);
6464
6465 // If printing assembly, use the recently updated abiflags information.
6466 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6467 // emitted at the end).
6468 getTargetStreamer().emitDirectiveModuleFP();
6469
Daniel Sanders7e527422014-07-10 13:38:23 +00006470 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006471 return false;
6472}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006473
Daniel Sanders7e527422014-07-10 13:38:23 +00006474bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006475 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006476 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006477 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006478 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006479
6480 if (Lexer.is(AsmToken::Identifier)) {
6481 StringRef Value = Parser.getTok().getString();
6482 Parser.Lex();
6483
6484 if (Value != "xx") {
6485 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6486 return false;
6487 }
6488
6489 if (!isABI_O32()) {
6490 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
6491 return false;
6492 }
6493
Daniel Sanders7e527422014-07-10 13:38:23 +00006494 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006495 if (ModuleLevelOptions) {
6496 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6497 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6498 } else {
6499 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6500 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6501 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006502 return true;
6503 }
6504
6505 if (Lexer.is(AsmToken::Integer)) {
6506 unsigned Value = Parser.getTok().getIntVal();
6507 Parser.Lex();
6508
6509 if (Value != 32 && Value != 64) {
6510 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6511 return false;
6512 }
6513
6514 if (Value == 32) {
6515 if (!isABI_O32()) {
6516 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6517 return false;
6518 }
6519
Daniel Sanders7e527422014-07-10 13:38:23 +00006520 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006521 if (ModuleLevelOptions) {
6522 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6523 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6524 } else {
6525 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6526 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6527 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006528 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006529 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006530 if (ModuleLevelOptions) {
6531 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6532 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6533 } else {
6534 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6535 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6536 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006537 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006538
Daniel Sanders7e527422014-07-10 13:38:23 +00006539 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006540 }
6541
6542 return false;
6543}
6544
Jack Carter0b744b32012-10-04 02:29:46 +00006545bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006546 // This returns false if this function recognizes the directive
6547 // regardless of whether it is successfully handles or reports an
6548 // error. Otherwise it returns true to give the generic parser a
6549 // chance at recognizing it.
6550
Rafael Espindola961d4692014-11-11 05:18:41 +00006551 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006552 StringRef IDVal = DirectiveID.getString();
6553
Nirav Dave996fc132016-05-05 14:15:46 +00006554 if (IDVal == ".cpload") {
6555 parseDirectiveCpLoad(DirectiveID.getLoc());
6556 return false;
6557 }
6558 if (IDVal == ".cprestore") {
6559 parseDirectiveCpRestore(DirectiveID.getLoc());
6560 return false;
6561 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006562 if (IDVal == ".dword") {
6563 parseDataDirective(8, DirectiveID.getLoc());
6564 return false;
6565 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006566 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006567 StringRef SymbolName;
6568
6569 if (Parser.parseIdentifier(SymbolName)) {
6570 reportParseError("expected identifier after .ent");
6571 return false;
6572 }
6573
6574 // There's an undocumented extension that allows an integer to
6575 // follow the name of the procedure which AFAICS is ignored by GAS.
6576 // Example: .ent foo,2
6577 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6578 if (getLexer().isNot(AsmToken::Comma)) {
6579 // Even though we accept this undocumented extension for compatibility
6580 // reasons, the additional integer argument does not actually change
6581 // the behaviour of the '.ent' directive, so we would like to discourage
6582 // its use. We do this by not referring to the extended version in
6583 // error messages which are not directly related to its use.
6584 reportParseError("unexpected token, expected end of statement");
6585 return false;
6586 }
6587 Parser.Lex(); // Eat the comma.
6588 const MCExpr *DummyNumber;
6589 int64_t DummyNumberVal;
6590 // If the user was explicitly trying to use the extended version,
6591 // we still give helpful extension-related error messages.
6592 if (Parser.parseExpression(DummyNumber)) {
6593 reportParseError("expected number after comma");
6594 return false;
6595 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006596 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006597 reportParseError("expected an absolute expression after comma");
6598 return false;
6599 }
6600 }
6601
6602 // If this is not the end of the statement, report an error.
6603 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6604 reportParseError("unexpected token, expected end of statement");
6605 return false;
6606 }
6607
Jim Grosbach6f482002015-05-18 18:43:14 +00006608 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006609
6610 getTargetStreamer().emitDirectiveEnt(*Sym);
6611 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006612 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006613 return false;
6614 }
6615
Jack Carter07c818d2013-01-25 01:31:34 +00006616 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006617 StringRef SymbolName;
6618
6619 if (Parser.parseIdentifier(SymbolName)) {
6620 reportParseError("expected identifier after .end");
6621 return false;
6622 }
6623
6624 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6625 reportParseError("unexpected token, expected end of statement");
6626 return false;
6627 }
6628
6629 if (CurrentFn == nullptr) {
6630 reportParseError(".end used without .ent");
6631 return false;
6632 }
6633
6634 if ((SymbolName != CurrentFn->getName())) {
6635 reportParseError(".end symbol does not match .ent symbol");
6636 return false;
6637 }
6638
6639 getTargetStreamer().emitDirectiveEnd(SymbolName);
6640 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006641 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006642 return false;
6643 }
6644
Jack Carter07c818d2013-01-25 01:31:34 +00006645 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006646 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6647 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006648 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006649 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6650 reportParseError("expected stack register");
6651 return false;
6652 }
6653
6654 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6655 if (!StackRegOpnd.isGPRAsmReg()) {
6656 reportParseError(StackRegOpnd.getStartLoc(),
6657 "expected general purpose register");
6658 return false;
6659 }
6660 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6661
6662 if (Parser.getTok().is(AsmToken::Comma))
6663 Parser.Lex();
6664 else {
6665 reportParseError("unexpected token, expected comma");
6666 return false;
6667 }
6668
6669 // Parse the frame size.
6670 const MCExpr *FrameSize;
6671 int64_t FrameSizeVal;
6672
6673 if (Parser.parseExpression(FrameSize)) {
6674 reportParseError("expected frame size value");
6675 return false;
6676 }
6677
Jim Grosbach13760bd2015-05-30 01:25:56 +00006678 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006679 reportParseError("frame size not an absolute expression");
6680 return false;
6681 }
6682
6683 if (Parser.getTok().is(AsmToken::Comma))
6684 Parser.Lex();
6685 else {
6686 reportParseError("unexpected token, expected comma");
6687 return false;
6688 }
6689
6690 // Parse the return register.
6691 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006692 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006693 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6694 reportParseError("expected return register");
6695 return false;
6696 }
6697
6698 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6699 if (!ReturnRegOpnd.isGPRAsmReg()) {
6700 reportParseError(ReturnRegOpnd.getStartLoc(),
6701 "expected general purpose register");
6702 return false;
6703 }
6704
6705 // If this is not the end of the statement, report an error.
6706 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6707 reportParseError("unexpected token, expected end of statement");
6708 return false;
6709 }
6710
6711 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6712 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006713 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006714 return false;
6715 }
6716
Jack Carter07c818d2013-01-25 01:31:34 +00006717 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006718 parseDirectiveSet();
6719 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006720 }
6721
Daniel Sandersd97a6342014-08-13 10:07:34 +00006722 if (IDVal == ".mask" || IDVal == ".fmask") {
6723 // .mask bitmask, frame_offset
6724 // bitmask: One bit for each register used.
6725 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6726 // first register is expected to be saved.
6727 // Examples:
6728 // .mask 0x80000000, -4
6729 // .fmask 0x80000000, -4
6730 //
Jack Carterbe332172012-09-07 00:48:02 +00006731
Daniel Sandersd97a6342014-08-13 10:07:34 +00006732 // Parse the bitmask
6733 const MCExpr *BitMask;
6734 int64_t BitMaskVal;
6735
6736 if (Parser.parseExpression(BitMask)) {
6737 reportParseError("expected bitmask value");
6738 return false;
6739 }
6740
Jim Grosbach13760bd2015-05-30 01:25:56 +00006741 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006742 reportParseError("bitmask not an absolute expression");
6743 return false;
6744 }
6745
6746 if (Parser.getTok().is(AsmToken::Comma))
6747 Parser.Lex();
6748 else {
6749 reportParseError("unexpected token, expected comma");
6750 return false;
6751 }
6752
6753 // Parse the frame_offset
6754 const MCExpr *FrameOffset;
6755 int64_t FrameOffsetVal;
6756
6757 if (Parser.parseExpression(FrameOffset)) {
6758 reportParseError("expected frame offset value");
6759 return false;
6760 }
6761
Jim Grosbach13760bd2015-05-30 01:25:56 +00006762 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006763 reportParseError("frame offset not an absolute expression");
6764 return false;
6765 }
6766
6767 // If this is not the end of the statement, report an error.
6768 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6769 reportParseError("unexpected token, expected end of statement");
6770 return false;
6771 }
6772
6773 if (IDVal == ".mask")
6774 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6775 else
6776 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006777 return false;
6778 }
6779
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006780 if (IDVal == ".nan")
6781 return parseDirectiveNaN();
6782
Jack Carter07c818d2013-01-25 01:31:34 +00006783 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006784 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006785 return false;
6786 }
6787
Rafael Espindolab59fb732014-03-28 18:50:26 +00006788 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006789 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006790 return false;
6791 }
6792
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006793 if (IDVal == ".dtprelword") {
6794 parseDirectiveDtpRelWord();
6795 return false;
6796 }
6797
6798 if (IDVal == ".dtpreldword") {
6799 parseDirectiveDtpRelDWord();
6800 return false;
6801 }
6802
6803 if (IDVal == ".tprelword") {
6804 parseDirectiveTpRelWord();
6805 return false;
6806 }
6807
6808 if (IDVal == ".tpreldword") {
6809 parseDirectiveTpRelDWord();
6810 return false;
6811 }
6812
Jack Carter07c818d2013-01-25 01:31:34 +00006813 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006814 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006815 return false;
6816 }
6817
Scott Egertond1aeb052016-02-15 16:11:51 +00006818 if (IDVal == ".hword") {
6819 parseDataDirective(2, DirectiveID.getLoc());
6820 return false;
6821 }
6822
Nirav Dave996fc132016-05-05 14:15:46 +00006823 if (IDVal == ".option") {
6824 parseDirectiveOption();
6825 return false;
6826 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006827
6828 if (IDVal == ".abicalls") {
6829 getTargetStreamer().emitDirectiveAbiCalls();
6830 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006831 Error(Parser.getTok().getLoc(),
6832 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006833 }
6834 return false;
6835 }
6836
Nirav Dave996fc132016-05-05 14:15:46 +00006837 if (IDVal == ".cpsetup") {
6838 parseDirectiveCPSetup();
6839 return false;
6840 }
6841 if (IDVal == ".cpreturn") {
6842 parseDirectiveCPReturn();
6843 return false;
6844 }
6845 if (IDVal == ".module") {
6846 parseDirectiveModule();
6847 return false;
6848 }
6849 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6850 parseInternalDirectiveReallowModule();
6851 return false;
6852 }
6853 if (IDVal == ".insn") {
6854 parseInsnDirective();
6855 return false;
6856 }
6857 if (IDVal == ".sbss") {
6858 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6859 return false;
6860 }
6861 if (IDVal == ".sdata") {
6862 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6863 return false;
6864 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006865
Rafael Espindola870c4e92012-01-11 03:56:41 +00006866 return true;
6867}
6868
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006869bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6870 // If this is not the end of the statement, report an error.
6871 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6872 reportParseError("unexpected token, expected end of statement");
6873 return false;
6874 }
6875
6876 getTargetStreamer().reallowModuleDirective();
6877
6878 getParser().Lex(); // Eat EndOfStatement token.
6879 return false;
6880}
6881
Rafael Espindola870c4e92012-01-11 03:56:41 +00006882extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00006883 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
6884 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
6885 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
6886 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00006887}
Jack Carterb4dbc172012-09-05 23:34:03 +00006888
6889#define GET_REGISTER_MATCHER
6890#define GET_MATCHER_IMPLEMENTATION
6891#include "MipsGenAsmMatcher.inc"