blob: 59f78ed5cd63f74712f5f8e6b8b13a9ce69ed528 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eugene Zelenkodde94e42017-01-30 23:21:32 +000010#include "MCTargetDesc/MipsABIFlagsSection.h"
Eric Christophera5762812015-01-26 17:33:46 +000011#include "MCTargetDesc/MipsABIInfo.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000012#include "MCTargetDesc/MipsBaseInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000013#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000014#include "MCTargetDesc/MipsMCTargetDesc.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Zoran Jovanovic375b60d2017-05-30 09:33:43 +000016#include "llvm/ADT/APFloat.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000017#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000018#include "llvm/ADT/SmallVector.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000019#include "llvm/ADT/StringRef.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "llvm/ADT/StringSwitch.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000021#include "llvm/ADT/Triple.h"
22#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000023#include "llvm/BinaryFormat/ELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCExpr.h"
26#include "llvm/MC/MCInst.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000027#include "llvm/MC/MCInstrDesc.h"
28#include "llvm/MC/MCObjectFileInfo.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000029#include "llvm/MC/MCParser/MCAsmLexer.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000030#include "llvm/MC/MCParser/MCAsmParser.h"
31#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000032#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000033#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000034#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000035#include "llvm/MC/MCStreamer.h"
36#include "llvm/MC/MCSubtargetInfo.h"
37#include "llvm/MC/MCSymbol.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000038#include "llvm/MC/MCSymbolELF.h"
39#include "llvm/MC/MCValue.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000043#include "llvm/Support/Debug.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000044#include "llvm/Support/ErrorHandling.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000045#include "llvm/Support/MathExtras.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000046#include "llvm/Support/SMLoc.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000047#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000048#include "llvm/Support/TargetRegistry.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000049#include "llvm/Support/raw_ostream.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000050#include <algorithm>
51#include <cassert>
52#include <cstdint>
Toma Tabacu9db22db2014-09-09 10:15:38 +000053#include <memory>
Eugene Zelenkodde94e42017-01-30 23:21:32 +000054#include <string>
55#include <utility>
Rafael Espindola870c4e92012-01-11 03:56:41 +000056
57using namespace llvm;
58
Chandler Carruthe96dd892014-04-21 22:55:11 +000059#define DEBUG_TYPE "mips-asm-parser"
60
Joey Gouly0e76fa72013-09-12 10:28:05 +000061namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000062
Joey Gouly0e76fa72013-09-12 10:28:05 +000063class MCInstrInfo;
Eugene Zelenkodde94e42017-01-30 23:21:32 +000064
65} // end namespace llvm
Joey Gouly0e76fa72013-09-12 10:28:05 +000066
Rafael Espindola870c4e92012-01-11 03:56:41 +000067namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000068
Jack Carter0b744b32012-10-04 02:29:46 +000069class MipsAssemblerOptions {
70public:
Eugene Zelenkodde94e42017-01-30 23:21:32 +000071 MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000072
Toma Tabacu9db22db2014-09-09 10:15:38 +000073 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000074 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000075 Reorder = Opts->isReorder();
76 Macro = Opts->isMacro();
77 Features = Opts->getFeatures();
78 }
79
Toma Tabacub19cf202015-04-27 13:12:59 +000080 unsigned getATRegIndex() const { return ATReg; }
81 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000082 if (Reg > 31)
83 return false;
84
85 ATReg = Reg;
86 return true;
87 }
Jack Carter0b744b32012-10-04 02:29:46 +000088
Toma Tabacu9db22db2014-09-09 10:15:38 +000089 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000090 void setReorder() { Reorder = true; }
91 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000092
Toma Tabacu9db22db2014-09-09 10:15:38 +000093 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000094 void setMacro() { Macro = true; }
95 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000096
Toma Tabacu465acfd2015-06-09 13:33:26 +000097 const FeatureBitset &getFeatures() const { return Features; }
98 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000099
Daniel Sandersf0df2212014-08-04 12:20:00 +0000100 // Set of features that are either architecture features or referenced
101 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
102 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
103 // The reason we need this mask is explained in the selectArch function.
104 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000105 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +0000106
Jack Carter0b744b32012-10-04 02:29:46 +0000107private:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000108 unsigned ATReg = 1;
109 bool Reorder = true;
110 bool Macro = true;
Toma Tabacu465acfd2015-06-09 13:33:26 +0000111 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +0000112};
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000113
114} // end anonymous namespace
Jack Carter0b744b32012-10-04 02:29:46 +0000115
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000116const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
117 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
118 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
119 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
120 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
121 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
122 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
123 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
124 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
125};
126
Jack Carter0b744b32012-10-04 02:29:46 +0000127namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000128
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000130 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000131 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000132 return static_cast<MipsTargetStreamer &>(TS);
133 }
134
Eric Christophera5762812015-01-26 17:33:46 +0000135 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000136 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000137 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
138 // nullptr, which indicates that no function is currently
139 // selected. This usually happens after an '.end func'
140 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000141 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000142 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000143 bool IsCpRestoreSet;
144 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000145 unsigned CpSaveLocation;
146 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
147 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000148
Daniel Sandersef638fe2014-10-03 15:37:37 +0000149 // Print a warning along with its fix-it message at the given range.
150 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
151 SMRange Range, bool ShowColors = true);
152
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000153#define GET_ASSEMBLER_HEADER
154#include "MipsGenAsmMatcher.inc"
155
Daniel Sandersc5537422016-07-27 13:49:44 +0000156 unsigned
157 checkEarlyTargetMatchPredicate(MCInst &Inst,
158 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000159 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
160
Chad Rosier49963552012-10-13 00:26:04 +0000161 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000162 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000163 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000164 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000165
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000166 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000167 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000168
Toma Tabacu13964452014-09-04 13:23:44 +0000169 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000170
Toma Tabacu13964452014-09-04 13:23:44 +0000171 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000172
Craig Topper55bc6cb2017-02-08 02:54:12 +0000173 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
174
David Blaikie960ea3f2014-06-08 16:18:35 +0000175 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
176 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000177
Craig Topper56c590a2014-04-29 07:58:02 +0000178 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000179
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000180 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
181 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000182 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000183 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000184 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
185 SMLoc S);
186 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
187 OperandMatchResultTy parseImm(OperandVector &Operands);
188 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
189 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000190 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
191 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
192 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000193
David Blaikie960ea3f2014-06-08 16:18:35 +0000194 bool searchSymbolAlias(OperandVector &Operands);
195
Toma Tabacu13964452014-09-04 13:23:44 +0000196 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000197
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000198 enum MacroExpanderResultTy {
199 MER_NotAMacro,
200 MER_Success,
201 MER_Fail,
202 };
Jack Carter30a59822012-10-04 04:03:53 +0000203
Matheus Almeida3813d572014-06-19 14:39:14 +0000204 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000205 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
206 MCStreamer &Out,
207 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000208
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000209 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
210 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000211
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000212 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000213 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000214 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000215
Toma Tabacuf712ede2015-06-17 14:31:51 +0000216 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
217 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000219
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000220 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
221
Toma Tabacu00e98672015-05-01 12:19:27 +0000222 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000223 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000224
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000225 bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU,
226 SMLoc IDLoc, MCStreamer &Out,
227 const MCSubtargetInfo *STI);
228
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000229 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
230 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000231 SMLoc IDLoc, MCStreamer &Out,
232 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000233
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000234 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000236
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000237 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000238 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
239
240 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
241 const MCSubtargetInfo *STI, bool IsImmOpnd);
242
243 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000245
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000246 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000248
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000249 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
250 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000251
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000252 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
253 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000254
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000255 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
256 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000257
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000258 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
259 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000260 const bool Signed);
261
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000262 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000263 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000264
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000265 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
266 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000267
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000268 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
269 const MCSubtargetInfo *STI);
270
271 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000272 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000273
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000274 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000275 MCStreamer &Out, const MCSubtargetInfo *STI);
276 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
277 const MCSubtargetInfo *STI);
278 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
279 const MCSubtargetInfo *STI);
280 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
281 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000282
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000283 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
284 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000285
Simon Dardis3c82a642017-02-08 16:25:05 +0000286 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
287 const MCSubtargetInfo *STI);
288
289 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
290 const MCSubtargetInfo *STI);
291
292 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
293 const MCSubtargetInfo *STI);
294
295 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
296 const MCSubtargetInfo *STI);
297
Simon Dardisaff4d142016-10-18 14:28:00 +0000298 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
299 const MCSubtargetInfo *STI, bool IsLoad);
300
Simon Dardis43115a12016-11-21 20:30:41 +0000301 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
302 const MCSubtargetInfo *STI);
303
304 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
305 const MCSubtargetInfo *STI);
306
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000307 bool reportParseError(Twine ErrorMsg);
308 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000309
Jack Carterb5cf5902013-04-17 00:18:04 +0000310 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000311
312 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000313 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000314 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000315 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000316 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000317 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000318 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000319 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000320 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000321 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000322 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000323 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000324 bool parseInsnDirective();
Simon Dardis1c73fcc2017-06-22 10:41:51 +0000325 bool parseRSectionDirective(StringRef Section);
Simon Atanasyanbe186202016-02-11 06:45:54 +0000326 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000327
328 bool parseSetAtDirective();
329 bool parseSetNoAtDirective();
330 bool parseSetMacroDirective();
331 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000332 bool parseSetMsaDirective();
333 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000334 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000335 bool parseSetReorderDirective();
336 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000337 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000338 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000339 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000340 bool parseSetOddSPRegDirective();
341 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000342 bool parseSetPopDirective();
343 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000344 bool parseSetSoftFloatDirective();
345 bool parseSetHardFloatDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +0000346 bool parseSetMtDirective();
347 bool parseSetNoMtDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000348
Jack Carterd76b2372013-03-21 21:44:16 +0000349 bool parseSetAssignment();
350
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000351 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000352 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000353 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000354 bool parseDirectiveDtpRelWord();
355 bool parseDirectiveDtpRelDWord();
356 bool parseDirectiveTpRelWord();
357 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000358 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000359 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000360 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
361 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000362
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000363 bool parseInternalDirectiveReallowModule();
364
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000365 bool eatComma(StringRef ErrorStr);
366
Jack Carter1ac53222013-02-20 23:11:17 +0000367 int matchCPURegisterName(StringRef Symbol);
368
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000369 int matchHWRegsRegisterName(StringRef Symbol);
370
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000371 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000372
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000373 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000374
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000375 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000376
Jack Carter5dc8ac92013-09-25 23:50:44 +0000377 int matchMSA128RegisterName(StringRef Name);
378
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000379 int matchMSA128CtrlRegisterName(StringRef Name);
380
Jack Carterd0bd6422013-04-18 00:41:53 +0000381 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000382
Toma Tabacu89a712b2015-04-15 10:48:56 +0000383 /// Returns the internal register number for the current AT. Also checks if
384 /// the current AT is unavailable (set to $0) and gives an error if it is.
385 /// This should be used in pseudo-instruction expansions which need AT.
386 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000387
Simon Dardis3aa8a902017-02-06 12:43:46 +0000388 bool canUseATReg();
389
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000390 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
391 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000392
393 // Helper function that checks if the value of a vector index is within the
394 // boundaries of accepted values for each RegisterKind
395 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
396 bool validateMSAIndex(int Val, int RegKind);
397
Daniel Sandersf0df2212014-08-04 12:20:00 +0000398 // Selects a new architecture by updating the FeatureBits with the necessary
399 // info including implied dependencies.
400 // Internally, it clears all the feature bits related to *any* architecture
401 // and selects the new one using the ToggleFeature functionality of the
402 // MCSubtargetInfo object that handles implied dependencies. The reason we
403 // clear all the arch related bits manually is because ToggleFeature only
404 // clears the features that imply the feature being cleared and not the
405 // features implied by the feature being cleared. This is easier to see
406 // with an example:
407 // --------------------------------------------------
408 // | Feature | Implies |
409 // | -------------------------------------------------|
410 // | FeatureMips1 | None |
411 // | FeatureMips2 | FeatureMips1 |
412 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
413 // | FeatureMips4 | FeatureMips3 |
414 // | ... | |
415 // --------------------------------------------------
416 //
417 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
418 // FeatureMipsGP64 | FeatureMips1)
419 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
420 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000421 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000422 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000423 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
424 STI.setFeatureBits(FeatureBits);
425 setAvailableFeatures(
426 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000427 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000428 }
429
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000430 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000431 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000432 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000433 setAvailableFeatures(
434 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000435 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000436 }
437 }
438
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000439 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000440 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000441 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000442 setAvailableFeatures(
443 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000444 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000445 }
446 }
447
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000448 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
449 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000450 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000451 }
452
453 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
454 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000455 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000456 }
457
Rafael Espindola870c4e92012-01-11 03:56:41 +0000458public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000459 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000460 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000461 Match_RequiresDifferentOperands,
462 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000463 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000464 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000465 Match_NonZeroOperandForSync,
Simon Dardis6f83ae32017-09-14 15:17:50 +0000466 Match_RequiresPosSizeRange0_32,
467 Match_RequiresPosSizeRange33_64,
Simon Dardis55e44672017-09-14 17:27:53 +0000468 Match_RequiresPosSizeUImm6,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000469#define GET_OPERAND_DIAGNOSTIC_TYPES
470#include "MipsGenAsmMatcher.inc"
471#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000472 };
473
Akira Hatanakab11ef082015-11-14 06:35:56 +0000474 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000475 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000476 : MCTargetAsmParser(Options, sti, MII),
Daniel Sanders50f17232015-09-15 16:17:27 +0000477 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
478 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000479 MCAsmParserExtension::Initialize(parser);
480
Toma Tabacu11e14a92015-04-21 11:50:52 +0000481 parser.addAliasForDirective(".asciiz", ".asciz");
482
Jack Carterb4dbc172012-09-05 23:34:03 +0000483 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000484 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000485
Toma Tabacu9db22db2014-09-09 10:15:38 +0000486 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000487 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000488 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000489
Toma Tabacu9db22db2014-09-09 10:15:38 +0000490 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000491 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000492 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000493
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000494 getTargetStreamer().updateABIInfo(*this);
495
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000496 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000497 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000498
499 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000500
Rafael Espindola699281c2016-05-18 11:58:50 +0000501 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000502
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000503 IsCpRestoreSet = false;
504 CpRestoreOffset = -1;
505
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000506 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000507 if ((TheTriple.getArch() == Triple::mips) ||
508 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000509 IsLittleEndian = false;
510 else
511 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000512 }
513
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000514 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
515 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
516
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000517 bool isGP64bit() const {
518 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
519 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000520
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000521 bool isFP64bit() const {
522 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
523 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000524
Eric Christophera5762812015-01-26 17:33:46 +0000525 const MipsABIInfo &getABI() const { return ABI; }
526 bool isABI_N32() const { return ABI.IsN32(); }
527 bool isABI_N64() const { return ABI.IsN64(); }
528 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000529 bool isABI_FPXX() const {
530 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
531 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000532
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000533 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000534 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000535 }
536
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000537 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000538 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000539 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000540
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000541 bool hasMips1() const {
542 return getSTI().getFeatureBits()[Mips::FeatureMips1];
543 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000544
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000545 bool hasMips2() const {
546 return getSTI().getFeatureBits()[Mips::FeatureMips2];
547 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000548
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000549 bool hasMips3() const {
550 return getSTI().getFeatureBits()[Mips::FeatureMips3];
551 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000552
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000553 bool hasMips4() const {
554 return getSTI().getFeatureBits()[Mips::FeatureMips4];
555 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000556
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000557 bool hasMips5() const {
558 return getSTI().getFeatureBits()[Mips::FeatureMips5];
559 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000560
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000561 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000562 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000563 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000564
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000565 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000566 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000567 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000568
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000569 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000570 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000571 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000572
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000573 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000574 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000575 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000576
Daniel Sanders17793142015-02-18 16:24:50 +0000577 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000578 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000579 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000580
Daniel Sanders17793142015-02-18 16:24:50 +0000581 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000582 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000583 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000584
Daniel Sanders17793142015-02-18 16:24:50 +0000585 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000586 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000587 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000588
Daniel Sanders17793142015-02-18 16:24:50 +0000589 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000590 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000591 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000592
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000593 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000594 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000595 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000596
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000597 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000598 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000599 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000600
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000601 bool hasDSP() const {
602 return getSTI().getFeatureBits()[Mips::FeatureDSP];
603 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000604
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000605 bool hasDSPR2() const {
606 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
607 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000608
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000609 bool hasDSPR3() const {
610 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
611 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000612
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000613 bool hasMSA() const {
614 return getSTI().getFeatureBits()[Mips::FeatureMSA];
615 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000616
Kai Nackee0245392015-01-27 19:11:28 +0000617 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000618 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000619 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000620
Daniel Sandersa6994442015-08-18 12:33:54 +0000621 bool inPicMode() {
622 return IsPicEnabled;
623 }
624
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000625 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000626 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000627 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000628
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000629 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000630 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000631 }
632
Eric Christophere8ae3e32015-05-07 23:10:21 +0000633 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000634 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000635 }
Simon Dardisae719c52017-07-11 18:03:20 +0000636 bool hasMT() const {
637 return getSTI().getFeatureBits()[Mips::FeatureMT];
638 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000639
Toma Tabacud9d344b2015-04-27 14:05:04 +0000640 /// Warn if RegIndex is the same as the current AT.
641 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000642
643 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000644
645 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000646
647 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
648 AsmToken::TokenKind OperatorToken,
649 MCContext &Ctx) override {
650 switch(OperatorToken) {
651 default:
652 llvm_unreachable("Unknown token");
653 return nullptr;
654 case AsmToken::PercentCall16:
655 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
656 case AsmToken::PercentCall_Hi:
657 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
658 case AsmToken::PercentCall_Lo:
659 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
660 case AsmToken::PercentDtprel_Hi:
661 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
662 case AsmToken::PercentDtprel_Lo:
663 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
664 case AsmToken::PercentGot:
665 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
666 case AsmToken::PercentGot_Disp:
667 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
668 case AsmToken::PercentGot_Hi:
669 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
670 case AsmToken::PercentGot_Lo:
671 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
672 case AsmToken::PercentGot_Ofst:
673 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
674 case AsmToken::PercentGot_Page:
675 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
676 case AsmToken::PercentGottprel:
677 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
678 case AsmToken::PercentGp_Rel:
679 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
680 case AsmToken::PercentHi:
681 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
682 case AsmToken::PercentHigher:
683 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
684 case AsmToken::PercentHighest:
685 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
686 case AsmToken::PercentLo:
687 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
688 case AsmToken::PercentNeg:
689 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
690 case AsmToken::PercentPcrel_Hi:
691 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
692 case AsmToken::PercentPcrel_Lo:
693 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
694 case AsmToken::PercentTlsgd:
695 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
696 case AsmToken::PercentTlsldm:
697 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
698 case AsmToken::PercentTprel_Hi:
699 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
700 case AsmToken::PercentTprel_Lo:
701 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
702 }
703 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000704};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000705
706/// MipsOperand - Instances of this class represent a parsed Mips machine
707/// instruction.
708class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000709public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000710 /// Broad categories of register classes
711 /// The exact class is finalized by the render method.
712 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000713 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000714 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000715 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000716 RegKind_FCC = 4, /// FCC
717 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
718 RegKind_MSACtrl = 16, /// MSA control registers
719 RegKind_COP2 = 32, /// COP2
720 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
721 /// context).
722 RegKind_CCR = 128, /// CCR
723 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000724 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000725 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000726 /// Potentially any (e.g. $1)
727 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
728 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000729 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000730 };
731
732private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000733 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000734 k_Immediate, /// An immediate (possibly involving symbol references)
735 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000736 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000737 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000738 k_RegList, /// A physical register list
739 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000740 } Kind;
741
David Blaikie960ea3f2014-06-08 16:18:35 +0000742public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000743 MipsOperand(KindTy K, MipsAsmParser &Parser)
744 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
745
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000746 ~MipsOperand() override {
747 switch (Kind) {
748 case k_Immediate:
749 break;
750 case k_Memory:
751 delete Mem.Base;
752 break;
753 case k_RegList:
754 delete RegList.List;
755 case k_RegisterIndex:
756 case k_Token:
757 case k_RegPair:
758 break;
759 }
760 }
761
David Blaikie960ea3f2014-06-08 16:18:35 +0000762private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000763 /// For diagnostics, and checking the assembler temporary
764 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000765
Eric Christopher8996c5d2013-03-15 00:42:55 +0000766 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000767 const char *Data;
768 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000769 };
770
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000771 struct RegIdxOp {
772 unsigned Index; /// Index into the register class
773 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000774 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000775 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000776 };
777
778 struct ImmOp {
779 const MCExpr *Val;
780 };
781
782 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000783 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000784 const MCExpr *Off;
785 };
786
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000787 struct RegListOp {
788 SmallVector<unsigned, 10> *List;
789 };
790
Jack Carterb4dbc172012-09-05 23:34:03 +0000791 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000792 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000793 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000794 struct ImmOp Imm;
795 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000796 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000797 };
798
799 SMLoc StartLoc, EndLoc;
800
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000801 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000802 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
803 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000804 const MCRegisterInfo *RegInfo,
805 SMLoc S, SMLoc E,
806 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000807 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000808 Op->RegIdx.Index = Index;
809 Op->RegIdx.RegInfo = RegInfo;
810 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000811 Op->RegIdx.Tok.Data = Str.data();
812 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000813 Op->StartLoc = S;
814 Op->EndLoc = E;
815 return Op;
816 }
817
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000818public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000819 /// Coerce the register to GPR32 and return the real register for the current
820 /// target.
821 unsigned getGPR32Reg() const {
822 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000823 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000824 unsigned ClassID = Mips::GPR32RegClassID;
825 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000826 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000827
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000828 /// Coerce the register to GPR32 and return the real register for the current
829 /// target.
830 unsigned getGPRMM16Reg() const {
831 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
832 unsigned ClassID = Mips::GPR32RegClassID;
833 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
834 }
835
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836 /// Coerce the register to GPR64 and return the real register for the current
837 /// target.
838 unsigned getGPR64Reg() const {
839 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
840 unsigned ClassID = Mips::GPR64RegClassID;
841 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000842 }
843
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000844private:
845 /// Coerce the register to AFGR64 and return the real register for the current
846 /// target.
847 unsigned getAFGR64Reg() const {
848 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
849 if (RegIdx.Index % 2 != 0)
850 AsmParser.Warning(StartLoc, "Float register should be even.");
851 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
852 .getRegister(RegIdx.Index / 2);
853 }
854
855 /// Coerce the register to FGR64 and return the real register for the current
856 /// target.
857 unsigned getFGR64Reg() const {
858 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
859 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
860 .getRegister(RegIdx.Index);
861 }
862
863 /// Coerce the register to FGR32 and return the real register for the current
864 /// target.
865 unsigned getFGR32Reg() const {
866 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
867 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
868 .getRegister(RegIdx.Index);
869 }
870
871 /// Coerce the register to FGRH32 and return the real register for the current
872 /// target.
873 unsigned getFGRH32Reg() const {
874 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
875 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
876 .getRegister(RegIdx.Index);
877 }
878
879 /// Coerce the register to FCC and return the real register for the current
880 /// target.
881 unsigned getFCCReg() const {
882 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
883 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
884 .getRegister(RegIdx.Index);
885 }
886
887 /// Coerce the register to MSA128 and return the real register for the current
888 /// target.
889 unsigned getMSA128Reg() const {
890 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
891 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
892 // identical
893 unsigned ClassID = Mips::MSA128BRegClassID;
894 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
895 }
896
897 /// Coerce the register to MSACtrl and return the real register for the
898 /// current target.
899 unsigned getMSACtrlReg() const {
900 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
901 unsigned ClassID = Mips::MSACtrlRegClassID;
902 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
903 }
904
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000905 /// Coerce the register to COP0 and return the real register for the
906 /// current target.
907 unsigned getCOP0Reg() const {
908 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
909 unsigned ClassID = Mips::COP0RegClassID;
910 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
911 }
912
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000913 /// Coerce the register to COP2 and return the real register for the
914 /// current target.
915 unsigned getCOP2Reg() const {
916 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
917 unsigned ClassID = Mips::COP2RegClassID;
918 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
919 }
920
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000921 /// Coerce the register to COP3 and return the real register for the
922 /// current target.
923 unsigned getCOP3Reg() const {
924 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
925 unsigned ClassID = Mips::COP3RegClassID;
926 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
927 }
928
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000929 /// Coerce the register to ACC64DSP and return the real register for the
930 /// current target.
931 unsigned getACC64DSPReg() const {
932 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
933 unsigned ClassID = Mips::ACC64DSPRegClassID;
934 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
935 }
936
937 /// Coerce the register to HI32DSP and return the real register for the
938 /// current target.
939 unsigned getHI32DSPReg() const {
940 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
941 unsigned ClassID = Mips::HI32DSPRegClassID;
942 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
943 }
944
945 /// Coerce the register to LO32DSP and return the real register for the
946 /// current target.
947 unsigned getLO32DSPReg() const {
948 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
949 unsigned ClassID = Mips::LO32DSPRegClassID;
950 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
951 }
952
953 /// Coerce the register to CCR and return the real register for the
954 /// current target.
955 unsigned getCCRReg() const {
956 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
957 unsigned ClassID = Mips::CCRRegClassID;
958 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
959 }
960
961 /// Coerce the register to HWRegs and return the real register for the
962 /// current target.
963 unsigned getHWRegsReg() const {
964 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
965 unsigned ClassID = Mips::HWRegsRegClassID;
966 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
967 }
968
969public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000970 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000971 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000972 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000973 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000974 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000975 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000976 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000977 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000978 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000979
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000980 void addRegOperands(MCInst &Inst, unsigned N) const {
981 llvm_unreachable("Use a custom parser instead");
982 }
983
Daniel Sanders21bce302014-04-01 12:35:23 +0000984 /// Render the operand to an MCInst as a GPR32
985 /// Asserts if the wrong number of operands are requested, or the operand
986 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +0000987 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
988 assert(N == 1 && "Invalid number of operands!");
989 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
990 }
991
992 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
993 assert(N == 1 && "Invalid number of operands!");
994 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
995 }
996
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000997 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
998 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000999 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001000 }
1001
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001002 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
1003 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001004 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001005 }
1006
Jozef Kolek1904fa22014-11-24 14:25:53 +00001007 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1008 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001009 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001010 }
1011
Zoran Jovanovic41688672015-02-10 16:36:20 +00001012 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1013 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001014 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001015 }
1016
Daniel Sanders21bce302014-04-01 12:35:23 +00001017 /// Render the operand to an MCInst as a GPR64
1018 /// Asserts if the wrong number of operands are requested, or the operand
1019 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001020 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1021 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001022 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001023 }
1024
1025 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1026 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001027 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001028 }
1029
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001030 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1031 assert(N == 1 && "Invalid number of operands!");
1032 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1033 }
1034
1035 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1036 assert(N == 1 && "Invalid number of operands!");
1037 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1038 }
1039
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001040 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1041 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001042 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001043 }
1044
1045 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1046 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001047 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001048 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001049 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001050 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001051 AsmParser.getParser().printError(
1052 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1053 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001054 }
1055
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001056 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1057 assert(N == 1 && "Invalid number of operands!");
1058 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1059 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1060 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1061 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1062 "registers");
1063 }
1064
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001065 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1066 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001067 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001068 }
1069
1070 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1071 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001072 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001073 }
1074
1075 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1076 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001077 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001078 }
1079
1080 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1081 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001082 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001083 }
1084
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001085 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1086 assert(N == 1 && "Invalid number of operands!");
1087 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1088 }
1089
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001090 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1091 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001092 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001093 }
1094
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001095 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1096 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001097 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001098 }
1099
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001100 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1101 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001102 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001103 }
1104
1105 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1106 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001107 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 }
1109
1110 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1111 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001112 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001113 }
1114
1115 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1116 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001117 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001118 }
1119
1120 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1121 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001122 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001123 }
1124
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001125 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001126 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1127 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001128 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001129 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001130 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001131 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001132 Inst.addOperand(MCOperand::createImm(Imm));
1133 }
1134
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001135 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001136 void addSImmOperands(MCInst &Inst, unsigned N) const {
1137 if (isImm() && !isConstantImm()) {
1138 addExpr(Inst, getImm());
1139 return;
1140 }
1141 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1142 }
1143
1144 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001145 void addUImmOperands(MCInst &Inst, unsigned N) const {
1146 if (isImm() && !isConstantImm()) {
1147 addExpr(Inst, getImm());
1148 return;
1149 }
1150 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1151 }
1152
Daniel Sanders78e89022016-03-11 11:37:50 +00001153 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1154 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1155 assert(N == 1 && "Invalid number of operands!");
1156 int64_t Imm = getConstantImm() - Offset;
1157 Imm = SignExtend64<Bits>(Imm);
1158 Imm += Offset;
1159 Imm += AdjustOffset;
1160 Inst.addOperand(MCOperand::createImm(Imm));
1161 }
1162
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001163 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001164 assert(N == 1 && "Invalid number of operands!");
1165 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001166 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001167 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001168
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001169 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001170 assert(N == 2 && "Invalid number of operands!");
1171
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001172 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1173 ? getMemBase()->getGPR64Reg()
1174 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001175
1176 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001177 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001178 }
1179
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001180 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1181 assert(N == 2 && "Invalid number of operands!");
1182
Jim Grosbache9119e42015-05-13 18:37:00 +00001183 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001184
1185 const MCExpr *Expr = getMemOff();
1186 addExpr(Inst, Expr);
1187 }
1188
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001189 void addRegListOperands(MCInst &Inst, unsigned N) const {
1190 assert(N == 1 && "Invalid number of operands!");
1191
1192 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001193 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001194 }
1195
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001196 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1197 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001198 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001199 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001200 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1201 Inst.addOperand(MCOperand::createReg(
1202 RegIdx.RegInfo->getRegClass(
1203 AsmParser.getABI().AreGprs64bit()
1204 ? Mips::GPR64RegClassID
1205 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1206 Inst.addOperand(MCOperand::createReg(
1207 RegIdx.RegInfo->getRegClass(
1208 AsmParser.getABI().AreGprs64bit()
1209 ? Mips::GPR64RegClassID
1210 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001211 }
1212
Zoran Jovanovic41688672015-02-10 16:36:20 +00001213 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1214 assert(N == 2 && "Invalid number of operands!");
1215 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001216 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001217 }
1218
Craig Topper56c590a2014-04-29 07:58:02 +00001219 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001220 // As a special case until we sort out the definition of div/divu, accept
1221 // $0/$zero here so that MCK_ZERO works correctly.
1222 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001223 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001224
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001225 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001226 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001227
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001228 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001229 int64_t Res;
1230 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001231 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001232
Daniel Sanders52da7af2015-11-06 12:11:03 +00001233 bool isConstantImmz() const {
1234 return isConstantImm() && getConstantImm() == 0;
1235 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001236
Daniel Sandersea4f6532015-11-06 12:22:31 +00001237 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1238 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1239 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001240
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001241 template <unsigned Bits> bool isSImm() const {
1242 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1243 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001244
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001245 template <unsigned Bits> bool isUImm() const {
1246 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1247 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001248
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001249 template <unsigned Bits> bool isAnyImm() const {
1250 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1251 isUInt<Bits>(getConstantImm()))
1252 : isImm();
1253 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001254
Daniel Sanders78e89022016-03-11 11:37:50 +00001255 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1256 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001257 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001258
Hrvoje Varga46458d02016-02-25 12:53:29 +00001259 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1260 return isConstantImm() && getConstantImm() >= Bottom &&
1261 getConstantImm() <= Top;
1262 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001263
Craig Topper56c590a2014-04-29 07:58:02 +00001264 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001265 // Note: It's not possible to pretend that other operand kinds are tokens.
1266 // The matcher emitter checks tokens first.
1267 return Kind == k_Token;
1268 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001269
Craig Topper56c590a2014-04-29 07:58:02 +00001270 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001271
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001272 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001273 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001274 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001275
Simon Dardis4ccda502016-05-27 13:56:36 +00001276 // Allow relocation operators.
1277 // FIXME: This predicate and others need to look through binary expressions
1278 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001279 template <unsigned Bits, unsigned ShiftAmount = 0>
1280 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001281 if (!isMem())
1282 return false;
1283 if (!getMemBase()->isGPRAsmReg())
1284 return false;
1285 if (isa<MCTargetExpr>(getMemOff()) ||
1286 (isConstantMemOff() &&
1287 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1288 return true;
1289 MCValue Res;
1290 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1291 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001292 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001293
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001294 bool isMemWithGRPMM16Base() const {
1295 return isMem() && getMemBase()->isMM16AsmReg();
1296 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001297
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001298 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1299 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1300 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1301 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001302
Jozef Kolek12c69822014-12-23 16:16:33 +00001303 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1304 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1305 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1306 && (getMemBase()->getGPR32Reg() == Mips::SP);
1307 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001308
Daniel Sanderse473dc92016-05-09 13:38:25 +00001309 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1310 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1311 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1312 && (getMemBase()->getGPR32Reg() == Mips::GP);
1313 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001314
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001315 template <unsigned Bits, unsigned ShiftLeftAmount>
1316 bool isScaledUImm() const {
1317 return isConstantImm() &&
1318 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001319 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001320
Daniel Sanders97297772016-03-22 14:40:00 +00001321 template <unsigned Bits, unsigned ShiftLeftAmount>
1322 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001323 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1324 return true;
1325 // Operand can also be a symbol or symbol plus offset in case of relocations.
1326 if (Kind != k_Immediate)
1327 return false;
1328 MCValue Res;
1329 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1330 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001331 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001332
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001333 bool isRegList16() const {
1334 if (!isRegList())
1335 return false;
1336
1337 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001338 if (Size < 2 || Size > 5)
1339 return false;
1340
1341 unsigned R0 = RegList.List->front();
1342 unsigned R1 = RegList.List->back();
1343 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1344 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001345 return false;
1346
1347 int PrevReg = *RegList.List->begin();
1348 for (int i = 1; i < Size - 1; i++) {
1349 int Reg = (*(RegList.List))[i];
1350 if ( Reg != PrevReg + 1)
1351 return false;
1352 PrevReg = Reg;
1353 }
1354
1355 return true;
1356 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001357
Vladimir Medic2b953d02013-10-01 09:48:56 +00001358 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001359
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001360 bool isLSAImm() const {
1361 if (!isConstantImm())
1362 return false;
1363 int64_t Val = getConstantImm();
1364 return 1 <= Val && Val <= 4;
1365 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001366
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001367 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001368
Zoran Jovanovic41688672015-02-10 16:36:20 +00001369 bool isMovePRegPair() const {
1370 if (Kind != k_RegList || RegList.List->size() != 2)
1371 return false;
1372
1373 unsigned R0 = RegList.List->front();
1374 unsigned R1 = RegList.List->back();
1375
1376 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1377 (R0 == Mips::A1 && R1 == Mips::A3) ||
1378 (R0 == Mips::A2 && R1 == Mips::A3) ||
1379 (R0 == Mips::A0 && R1 == Mips::S5) ||
1380 (R0 == Mips::A0 && R1 == Mips::S6) ||
1381 (R0 == Mips::A0 && R1 == Mips::A1) ||
1382 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001383 (R0 == Mips::A0 && R1 == Mips::A3) ||
1384 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1385 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1386 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1387 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1388 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1389 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1390 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1391 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001392 return true;
1393
1394 return false;
1395 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001396
1397 StringRef getToken() const {
1398 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001399 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001400 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001401
Zlatko Buljanba553a62016-05-09 08:07:28 +00001402 bool isRegPair() const {
1403 return Kind == k_RegPair && RegIdx.Index <= 30;
1404 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001405
Craig Topper56c590a2014-04-29 07:58:02 +00001406 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001407 // As a special case until we sort out the definition of div/divu, accept
1408 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001409 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1410 RegIdx.Kind & RegKind_GPR)
1411 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001412
Daniel Sanders976d9382016-07-05 13:38:40 +00001413 llvm_unreachable("Invalid access!");
1414 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001415 }
1416
Jack Carterb4dbc172012-09-05 23:34:03 +00001417 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001418 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001419 return Imm.Val;
1420 }
1421
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001422 int64_t getConstantImm() const {
1423 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001424 int64_t Value = 0;
1425 (void)Val->evaluateAsAbsolute(Value);
1426 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001427 }
1428
1429 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001430 assert((Kind == k_Memory) && "Invalid access!");
1431 return Mem.Base;
1432 }
1433
1434 const MCExpr *getMemOff() const {
1435 assert((Kind == k_Memory) && "Invalid access!");
1436 return Mem.Off;
1437 }
1438
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001439 int64_t getConstantMemOff() const {
1440 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1441 }
1442
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001443 const SmallVectorImpl<unsigned> &getRegList() const {
1444 assert((Kind == k_RegList) && "Invalid access!");
1445 return *(RegList.List);
1446 }
1447
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001448 unsigned getRegPair() const {
1449 assert((Kind == k_RegPair) && "Invalid access!");
1450 return RegIdx.Index;
1451 }
1452
David Blaikie960ea3f2014-06-08 16:18:35 +00001453 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1454 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001455 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001456 Op->Tok.Data = Str.data();
1457 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001458 Op->StartLoc = S;
1459 Op->EndLoc = S;
1460 return Op;
1461 }
1462
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001463 /// Create a numeric register (e.g. $1). The exact register remains
1464 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001465 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001466 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1467 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001468 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001469 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001470 }
1471
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001472 /// Create a register that is definitely a GPR.
1473 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001474 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001475 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1476 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1477 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001478 }
1479
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001480 /// Create a register that is definitely a FGR.
1481 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001482 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001483 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1484 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1485 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001486 }
1487
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001488 /// Create a register that is definitely a HWReg.
1489 /// This is typically only used for named registers such as $hwr_cpunum.
1490 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001491 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001492 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001493 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001494 }
1495
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001496 /// Create a register that is definitely an FCC.
1497 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001498 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001499 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1500 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1501 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001502 }
1503
1504 /// Create a register that is definitely an ACC.
1505 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001506 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001507 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1508 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1509 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001510 }
1511
1512 /// Create a register that is definitely an MSA128.
1513 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001514 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001515 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1516 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1517 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001518 }
1519
1520 /// Create a register that is definitely an MSACtrl.
1521 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001522 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001523 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1524 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1525 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001526 }
1527
David Blaikie960ea3f2014-06-08 16:18:35 +00001528 static std::unique_ptr<MipsOperand>
1529 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001530 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001531 Op->Imm.Val = Val;
1532 Op->StartLoc = S;
1533 Op->EndLoc = E;
1534 return Op;
1535 }
1536
David Blaikie960ea3f2014-06-08 16:18:35 +00001537 static std::unique_ptr<MipsOperand>
1538 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1539 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001540 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001541 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001542 Op->Mem.Off = Off;
1543 Op->StartLoc = S;
1544 Op->EndLoc = E;
1545 return Op;
1546 }
1547
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001548 static std::unique_ptr<MipsOperand>
1549 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1550 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001551 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001552
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001553 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001554 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001555 Op->StartLoc = StartLoc;
1556 Op->EndLoc = EndLoc;
1557 return Op;
1558 }
1559
Daniel Sandersd044e492016-05-09 13:10:57 +00001560 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1561 SMLoc S, SMLoc E,
1562 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001563 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001564 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001565 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1566 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001567 Op->StartLoc = S;
1568 Op->EndLoc = E;
1569 return Op;
1570 }
1571
Simon Dardis509da1a2017-02-13 16:06:48 +00001572 bool isGPRZeroAsmReg() const {
1573 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1574 }
1575
1576 bool isGPRNonZeroAsmReg() const {
1577 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1578 RegIdx.Index <= 31;
1579 }
1580
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001581 bool isGPRAsmReg() const {
1582 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001583 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001584
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001585 bool isMM16AsmReg() const {
1586 if (!(isRegIdx() && RegIdx.Kind))
1587 return false;
1588 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1589 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001590
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001591 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001592 bool isMM16AsmRegZero() const {
1593 if (!(isRegIdx() && RegIdx.Kind))
1594 return false;
1595 return (RegIdx.Index == 0 ||
1596 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1597 RegIdx.Index == 17);
1598 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001599
Zoran Jovanovic41688672015-02-10 16:36:20 +00001600 bool isMM16AsmRegMoveP() const {
1601 if (!(isRegIdx() && RegIdx.Kind))
1602 return false;
1603 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1604 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1605 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001606
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001607 bool isFGRAsmReg() const {
1608 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1609 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001610 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001611
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001612 bool isStrictlyFGRAsmReg() const {
1613 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1614 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1615 }
1616
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001617 bool isHWRegsAsmReg() const {
1618 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001619 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001620
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001621 bool isCCRAsmReg() const {
1622 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001623 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001624
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001625 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001626 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1627 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001628 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001629 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001630
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001631 bool isACCAsmReg() const {
1632 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001633 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001634
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001635 bool isCOP0AsmReg() const {
1636 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1637 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001638
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001639 bool isCOP2AsmReg() const {
1640 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001641 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001642
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001643 bool isCOP3AsmReg() const {
1644 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1645 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001646
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001647 bool isMSA128AsmReg() const {
1648 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001649 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001650
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001651 bool isMSACtrlAsmReg() const {
1652 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001653 }
1654
Jack Carterb4dbc172012-09-05 23:34:03 +00001655 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001656 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001657 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001658 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001659
Craig Topper56c590a2014-04-29 07:58:02 +00001660 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001661 switch (Kind) {
1662 case k_Immediate:
1663 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001664 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001665 OS << ">";
1666 break;
1667 case k_Memory:
1668 OS << "Mem<";
1669 Mem.Base->print(OS);
1670 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001671 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001672 OS << ">";
1673 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001674 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001675 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1676 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001677 break;
1678 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001679 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001680 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001681 case k_RegList:
1682 OS << "RegList< ";
1683 for (auto Reg : (*RegList.List))
1684 OS << Reg << " ";
1685 OS << ">";
1686 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001687 case k_RegPair:
1688 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1689 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001690 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001691 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001692
1693 bool isValidForTie(const MipsOperand &Other) const {
1694 if (Kind != Other.Kind)
1695 return false;
1696
1697 switch (Kind) {
1698 default:
1699 llvm_unreachable("Unexpected kind");
1700 return false;
1701 case k_RegisterIndex: {
1702 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1703 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1704 return Token == OtherToken;
1705 }
1706 }
1707 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001708}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001709
1710} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001711
Jack Carter9e65aa32013-03-22 00:05:30 +00001712namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001713
Jack Carter9e65aa32013-03-22 00:05:30 +00001714extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001715
1716} // end namespace llvm
1717
Jack Carter9e65aa32013-03-22 00:05:30 +00001718static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1719 return MipsInsts[Opcode];
1720}
1721
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001722static bool hasShortDelaySlot(unsigned Opcode) {
1723 switch (Opcode) {
1724 case Mips::JALS_MM:
1725 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001726 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001727 case Mips::BGEZALS_MM:
1728 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001729 return true;
1730 default:
1731 return false;
1732 }
1733}
1734
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001735static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1736 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1737 return &SRExpr->getSymbol();
1738 }
1739
1740 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1741 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1742 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1743
1744 if (LHSSym)
1745 return LHSSym;
1746
1747 if (RHSSym)
1748 return RHSSym;
1749
1750 return nullptr;
1751 }
1752
1753 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1754 return getSingleMCSymbol(UExpr->getSubExpr());
1755
1756 return nullptr;
1757}
1758
1759static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1760 if (isa<MCSymbolRefExpr>(Expr))
1761 return 1;
1762
1763 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1764 return countMCSymbolRefExpr(BExpr->getLHS()) +
1765 countMCSymbolRefExpr(BExpr->getRHS());
1766
1767 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1768 return countMCSymbolRefExpr(UExpr->getSubExpr());
1769
1770 return 0;
1771}
1772
Jack Carter9e65aa32013-03-22 00:05:30 +00001773bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001774 MCStreamer &Out,
1775 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001776 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001777 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001778 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001779
Jack Carter9e65aa32013-03-22 00:05:30 +00001780 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001781
1782 if (MCID.isBranch() || MCID.isCall()) {
1783 const unsigned Opcode = Inst.getOpcode();
1784 MCOperand Offset;
1785
1786 switch (Opcode) {
1787 default:
1788 break;
Kai Nackee0245392015-01-27 19:11:28 +00001789 case Mips::BBIT0:
1790 case Mips::BBIT032:
1791 case Mips::BBIT1:
1792 case Mips::BBIT132:
1793 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001794 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001795
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001796 case Mips::BEQ:
1797 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001798 case Mips::BEQ_MM:
1799 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001800 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001801 Offset = Inst.getOperand(2);
1802 if (!Offset.isImm())
1803 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001804 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001805 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001806 if (OffsetToAlignment(Offset.getImm(),
1807 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001808 return Error(IDLoc, "branch to misaligned address");
1809 break;
1810 case Mips::BGEZ:
1811 case Mips::BGTZ:
1812 case Mips::BLEZ:
1813 case Mips::BLTZ:
1814 case Mips::BGEZAL:
1815 case Mips::BLTZAL:
1816 case Mips::BC1F:
1817 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001818 case Mips::BGEZ_MM:
1819 case Mips::BGTZ_MM:
1820 case Mips::BLEZ_MM:
1821 case Mips::BLTZ_MM:
1822 case Mips::BGEZAL_MM:
1823 case Mips::BLTZAL_MM:
1824 case Mips::BC1F_MM:
1825 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001826 case Mips::BC1EQZC_MMR6:
1827 case Mips::BC1NEZC_MMR6:
1828 case Mips::BC2EQZC_MMR6:
1829 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001830 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001831 Offset = Inst.getOperand(1);
1832 if (!Offset.isImm())
1833 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001834 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001835 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001836 if (OffsetToAlignment(Offset.getImm(),
1837 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001838 return Error(IDLoc, "branch to misaligned address");
1839 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001840 case Mips::BGEC: case Mips::BGEC_MMR6:
1841 case Mips::BLTC: case Mips::BLTC_MMR6:
1842 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1843 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1844 case Mips::BEQC: case Mips::BEQC_MMR6:
1845 case Mips::BNEC: case Mips::BNEC_MMR6:
1846 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1847 Offset = Inst.getOperand(2);
1848 if (!Offset.isImm())
1849 break; // We'll deal with this situation later on when applying fixups.
1850 if (!isIntN(18, Offset.getImm()))
1851 return Error(IDLoc, "branch target out of range");
1852 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1853 return Error(IDLoc, "branch to misaligned address");
1854 break;
1855 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1856 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1857 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1858 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1859 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1860 Offset = Inst.getOperand(1);
1861 if (!Offset.isImm())
1862 break; // We'll deal with this situation later on when applying fixups.
1863 if (!isIntN(18, Offset.getImm()))
1864 return Error(IDLoc, "branch target out of range");
1865 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1866 return Error(IDLoc, "branch to misaligned address");
1867 break;
1868 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1869 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1870 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1871 Offset = Inst.getOperand(1);
1872 if (!Offset.isImm())
1873 break; // We'll deal with this situation later on when applying fixups.
1874 if (!isIntN(23, Offset.getImm()))
1875 return Error(IDLoc, "branch target out of range");
1876 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1877 return Error(IDLoc, "branch to misaligned address");
1878 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001879 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001880 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001881 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001882 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001883 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1884 Offset = Inst.getOperand(1);
1885 if (!Offset.isImm())
1886 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001887 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001888 return Error(IDLoc, "branch target out of range");
1889 if (OffsetToAlignment(Offset.getImm(), 2LL))
1890 return Error(IDLoc, "branch to misaligned address");
1891 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001892 }
1893 }
1894
Daniel Sandersa84989a2014-06-16 13:25:35 +00001895 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1896 // We still accept it but it is a normal nop.
1897 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1898 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1899 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1900 "nop instruction");
1901 }
1902
Kai Nackee0245392015-01-27 19:11:28 +00001903 if (hasCnMips()) {
1904 const unsigned Opcode = Inst.getOpcode();
1905 MCOperand Opnd;
1906 int Imm;
1907
1908 switch (Opcode) {
1909 default:
1910 break;
1911
1912 case Mips::BBIT0:
1913 case Mips::BBIT032:
1914 case Mips::BBIT1:
1915 case Mips::BBIT132:
1916 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1917 // The offset is handled above
1918 Opnd = Inst.getOperand(1);
1919 if (!Opnd.isImm())
1920 return Error(IDLoc, "expected immediate operand kind");
1921 Imm = Opnd.getImm();
1922 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1923 Opcode == Mips::BBIT1 ? 63 : 31))
1924 return Error(IDLoc, "immediate operand value out of range");
1925 if (Imm > 31) {
1926 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1927 : Mips::BBIT132);
1928 Inst.getOperand(1).setImm(Imm - 32);
1929 }
1930 break;
1931
Kai Nackee0245392015-01-27 19:11:28 +00001932 case Mips::SEQi:
1933 case Mips::SNEi:
1934 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1935 Opnd = Inst.getOperand(2);
1936 if (!Opnd.isImm())
1937 return Error(IDLoc, "expected immediate operand kind");
1938 Imm = Opnd.getImm();
1939 if (!isInt<10>(Imm))
1940 return Error(IDLoc, "immediate operand value out of range");
1941 break;
1942 }
1943 }
1944
Simon Dardis509da1a2017-02-13 16:06:48 +00001945 // Warn on division by zero. We're checking here as all instructions get
1946 // processed here, not just the macros that need expansion.
1947 //
1948 // The MIPS backend models most of the divison instructions and macros as
1949 // three operand instructions. The pre-R6 divide instructions however have
1950 // two operands and explicitly define HI/LO as part of the instruction,
1951 // not in the operands.
1952 unsigned FirstOp = 1;
1953 unsigned SecondOp = 2;
1954 switch (Inst.getOpcode()) {
1955 default:
1956 break;
1957 case Mips::SDivIMacro:
1958 case Mips::UDivIMacro:
1959 case Mips::DSDivIMacro:
1960 case Mips::DUDivIMacro:
1961 if (Inst.getOperand(2).getImm() == 0) {
1962 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1963 Inst.getOperand(1).getReg() == Mips::ZERO_64)
1964 Warning(IDLoc, "dividing zero by zero");
1965 else
1966 Warning(IDLoc, "division by zero");
1967 }
1968 break;
1969 case Mips::DSDIV:
1970 case Mips::SDIV:
1971 case Mips::UDIV:
1972 case Mips::DUDIV:
1973 case Mips::UDIV_MM:
1974 case Mips::SDIV_MM:
1975 FirstOp = 0;
1976 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00001977 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00001978 case Mips::SDivMacro:
1979 case Mips::DSDivMacro:
1980 case Mips::UDivMacro:
1981 case Mips::DUDivMacro:
1982 case Mips::DIV:
1983 case Mips::DIVU:
1984 case Mips::DDIV:
1985 case Mips::DDIVU:
1986 case Mips::DIVU_MMR6:
1987 case Mips::DDIVU_MM64R6:
1988 case Mips::DIV_MMR6:
1989 case Mips::DDIV_MM64R6:
1990 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
1991 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
1992 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
1993 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
1994 Warning(IDLoc, "dividing zero by zero");
1995 else
1996 Warning(IDLoc, "division by zero");
1997 }
1998 break;
1999 }
2000
Simon Atanasyan50485142016-12-12 17:40:26 +00002001 // For PIC code convert unconditional jump to unconditional branch.
2002 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
2003 inPicMode()) {
2004 MCInst BInst;
2005 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
2006 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2007 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2008 BInst.addOperand(Inst.getOperand(0));
2009 Inst = BInst;
2010 }
2011
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002012 // This expansion is not in a function called by tryExpandInstruction()
2013 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002014 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2015 inPicMode()) {
2016 warnIfNoMacro(IDLoc);
2017
2018 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2019
2020 // We can do this expansion if there's only 1 symbol in the argument
2021 // expression.
2022 if (countMCSymbolRefExpr(JalExpr) > 1)
2023 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2024
2025 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002026 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002027 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2028
2029 // FIXME: Add support for label+offset operands (currently causes an error).
2030 // FIXME: Add support for forward-declared local symbols.
2031 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002032 if (JalSym->isInSection() || JalSym->isTemporary() ||
2033 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002034 if (isABI_O32()) {
2035 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002036 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002037 // R_(MICRO)MIPS_GOT16 label
2038 // addiu $25, $25, 0
2039 // R_(MICRO)MIPS_LO16 label
2040 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002041 const MCExpr *Got16RelocExpr =
2042 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2043 const MCExpr *Lo16RelocExpr =
2044 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002045
Daniel Sandersa736b372016-04-29 13:33:12 +00002046 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2047 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2048 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2049 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002050 } else if (isABI_N32() || isABI_N64()) {
2051 // If it's a local symbol and the N32/N64 ABIs are being used,
2052 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002053 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002054 // R_(MICRO)MIPS_GOT_DISP label
2055 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002056 const MCExpr *GotDispRelocExpr =
2057 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002058
Daniel Sandersa736b372016-04-29 13:33:12 +00002059 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2060 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2061 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002062 }
2063 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002064 // If it's an external/weak symbol, we expand to:
2065 // lw/ld $25, 0($gp)
2066 // R_(MICRO)MIPS_CALL16 label
2067 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002068 const MCExpr *Call16RelocExpr =
2069 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002070
Daniel Sandersa736b372016-04-29 13:33:12 +00002071 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2072 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002073 }
2074
2075 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002076 if (IsCpRestoreSet && inMicroMipsMode())
2077 JalrInst.setOpcode(Mips::JALRS_MM);
2078 else
2079 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002080 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2081 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2082
2083 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2084 // This relocation is supposed to be an optimization hint for the linker
2085 // and is not necessary for correctness.
2086
2087 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002088 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002089 }
2090
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002091 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2092 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002093 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002094 // reference or immediate we may have to expand instructions.
2095 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002096 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002097 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2098 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002099 MCOperand &Op = Inst.getOperand(i);
2100 if (Op.isImm()) {
2101 int MemOffset = Op.getImm();
2102 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002103 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002104 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00002105 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002106 }
2107 } else if (Op.isExpr()) {
2108 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002109 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002110 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002111 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002112 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002113 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002114 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002115 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002116 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002117 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002118 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002119 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002120 }
2121 }
2122 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002123 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002124 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002125
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002126 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002127 if (MCID.mayLoad()) {
2128 // Try to create 16-bit GP relative load instruction.
2129 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2130 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2131 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2132 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2133 MCOperand &Op = Inst.getOperand(i);
2134 if (Op.isImm()) {
2135 int MemOffset = Op.getImm();
2136 MCOperand &DstReg = Inst.getOperand(0);
2137 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002138 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002139 getContext().getRegisterInfo()->getRegClass(
2140 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002141 (BaseReg.getReg() == Mips::GP ||
2142 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002143
Daniel Sandersa736b372016-04-29 13:33:12 +00002144 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2145 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002146 return false;
2147 }
2148 }
2149 }
2150 } // for
2151 } // if load
2152
2153 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2154
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002155 MCOperand Opnd;
2156 int Imm;
2157
2158 switch (Inst.getOpcode()) {
2159 default:
2160 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002161 case Mips::ADDIUSP_MM:
2162 Opnd = Inst.getOperand(0);
2163 if (!Opnd.isImm())
2164 return Error(IDLoc, "expected immediate operand kind");
2165 Imm = Opnd.getImm();
2166 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2167 Imm % 4 != 0)
2168 return Error(IDLoc, "immediate operand value out of range");
2169 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002170 case Mips::SLL16_MM:
2171 case Mips::SRL16_MM:
2172 Opnd = Inst.getOperand(2);
2173 if (!Opnd.isImm())
2174 return Error(IDLoc, "expected immediate operand kind");
2175 Imm = Opnd.getImm();
2176 if (Imm < 1 || Imm > 8)
2177 return Error(IDLoc, "immediate operand value out of range");
2178 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002179 case Mips::LI16_MM:
2180 Opnd = Inst.getOperand(1);
2181 if (!Opnd.isImm())
2182 return Error(IDLoc, "expected immediate operand kind");
2183 Imm = Opnd.getImm();
2184 if (Imm < -1 || Imm > 126)
2185 return Error(IDLoc, "immediate operand value out of range");
2186 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002187 case Mips::ADDIUR2_MM:
2188 Opnd = Inst.getOperand(2);
2189 if (!Opnd.isImm())
2190 return Error(IDLoc, "expected immediate operand kind");
2191 Imm = Opnd.getImm();
2192 if (!(Imm == 1 || Imm == -1 ||
2193 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2194 return Error(IDLoc, "immediate operand value out of range");
2195 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002196 case Mips::ANDI16_MM:
2197 Opnd = Inst.getOperand(2);
2198 if (!Opnd.isImm())
2199 return Error(IDLoc, "expected immediate operand kind");
2200 Imm = Opnd.getImm();
2201 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2202 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2203 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2204 return Error(IDLoc, "immediate operand value out of range");
2205 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002206 case Mips::LBU16_MM:
2207 Opnd = Inst.getOperand(2);
2208 if (!Opnd.isImm())
2209 return Error(IDLoc, "expected immediate operand kind");
2210 Imm = Opnd.getImm();
2211 if (Imm < -1 || Imm > 14)
2212 return Error(IDLoc, "immediate operand value out of range");
2213 break;
2214 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002215 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002216 Opnd = Inst.getOperand(2);
2217 if (!Opnd.isImm())
2218 return Error(IDLoc, "expected immediate operand kind");
2219 Imm = Opnd.getImm();
2220 if (Imm < 0 || Imm > 15)
2221 return Error(IDLoc, "immediate operand value out of range");
2222 break;
2223 case Mips::LHU16_MM:
2224 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002225 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002226 Opnd = Inst.getOperand(2);
2227 if (!Opnd.isImm())
2228 return Error(IDLoc, "expected immediate operand kind");
2229 Imm = Opnd.getImm();
2230 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2231 return Error(IDLoc, "immediate operand value out of range");
2232 break;
2233 case Mips::LW16_MM:
2234 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002235 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002236 Opnd = Inst.getOperand(2);
2237 if (!Opnd.isImm())
2238 return Error(IDLoc, "expected immediate operand kind");
2239 Imm = Opnd.getImm();
2240 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2241 return Error(IDLoc, "immediate operand value out of range");
2242 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002243 case Mips::ADDIUPC_MM:
2244 MCOperand Opnd = Inst.getOperand(1);
2245 if (!Opnd.isImm())
2246 return Error(IDLoc, "expected immediate operand kind");
2247 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002248 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002249 return Error(IDLoc, "immediate operand value out of range");
2250 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002251 }
2252 }
2253
Daniel Sandersd8c07762016-04-18 12:35:36 +00002254 bool FillDelaySlot =
2255 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2256 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002257 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002258
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002259 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002260 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002261 switch (ExpandResult) {
2262 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002263 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002264 break;
2265 case MER_Success:
2266 break;
2267 case MER_Fail:
2268 return true;
2269 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002270
Daniel Sanderscda908a2016-05-16 09:10:13 +00002271 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2272 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2273 if (inMicroMipsMode())
2274 TOut.setUsesMicroMips();
2275
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002276 // If this instruction has a delay slot and .set reorder is active,
2277 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002278 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002279 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2280 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002281 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002282
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002283 if ((Inst.getOpcode() == Mips::JalOneReg ||
2284 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2285 isPicAndNotNxxAbi()) {
2286 if (IsCpRestoreSet) {
2287 // We need a NOP between the JALR and the LW:
2288 // If .set reorder has been used, we've already emitted a NOP.
2289 // If .set noreorder has been used, we need to emit a NOP at this point.
2290 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002291 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2292 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002293
2294 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002295 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002296 } else
2297 Warning(IDLoc, "no .cprestore used in PIC mode");
2298 }
2299
Jack Carter9e65aa32013-03-22 00:05:30 +00002300 return false;
2301}
2302
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002303MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002304MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2305 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002306 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002307 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002308 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002309 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002310 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002311 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002312 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002313 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002314 case Mips::LoadAddrImm64:
2315 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2316 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2317 "expected immediate operand kind");
2318
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002319 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2320 Inst.getOperand(1),
2321 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002322 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002323 ? MER_Fail
2324 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002325 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002326 case Mips::LoadAddrReg64:
2327 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2328 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2329 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2330 "expected immediate operand kind");
2331
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002332 return expandLoadAddress(Inst.getOperand(0).getReg(),
2333 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2334 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002335 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002336 ? MER_Fail
2337 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002338 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002339 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002340 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2341 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002342 case Mips::SWM_MM:
2343 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002344 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2345 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002346 case Mips::JalOneReg:
2347 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002348 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002349 case Mips::BneImm:
2350 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002351 case Mips::BEQLImmMacro:
2352 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002353 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002354 case Mips::BLT:
2355 case Mips::BLE:
2356 case Mips::BGE:
2357 case Mips::BGT:
2358 case Mips::BLTU:
2359 case Mips::BLEU:
2360 case Mips::BGEU:
2361 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002362 case Mips::BLTL:
2363 case Mips::BLEL:
2364 case Mips::BGEL:
2365 case Mips::BGTL:
2366 case Mips::BLTUL:
2367 case Mips::BLEUL:
2368 case Mips::BGEUL:
2369 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002370 case Mips::BLTImmMacro:
2371 case Mips::BLEImmMacro:
2372 case Mips::BGEImmMacro:
2373 case Mips::BGTImmMacro:
2374 case Mips::BLTUImmMacro:
2375 case Mips::BLEUImmMacro:
2376 case Mips::BGEUImmMacro:
2377 case Mips::BGTUImmMacro:
2378 case Mips::BLTLImmMacro:
2379 case Mips::BLELImmMacro:
2380 case Mips::BGELImmMacro:
2381 case Mips::BGTLImmMacro:
2382 case Mips::BLTULImmMacro:
2383 case Mips::BLEULImmMacro:
2384 case Mips::BGEULImmMacro:
2385 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002386 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002387 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002388 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002389 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2390 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002391 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002392 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002393 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2394 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002395 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002396 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002397 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2398 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002399 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002400 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002401 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2402 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002403 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002404 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2405 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002406 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002407 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002408 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002409 case Mips::PseudoTRUNC_W_D:
2410 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2411 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002412
2413 case Mips::LoadImmSingleGPR:
2414 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2415 ? MER_Fail
2416 : MER_Success;
2417 case Mips::LoadImmSingleFGR:
2418 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2419 ? MER_Fail
2420 : MER_Success;
2421 case Mips::LoadImmDoubleGPR:
2422 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2423 ? MER_Fail
2424 : MER_Success;
2425 case Mips::LoadImmDoubleFGR:
2426 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2427 ? MER_Fail
2428 : MER_Success;
2429 case Mips::LoadImmDoubleFGR_32:
2430 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2431 ? MER_Fail
2432 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002433 case Mips::Ulh:
2434 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2435 case Mips::Ulhu:
2436 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002437 case Mips::Ush:
2438 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002439 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002440 case Mips::Usw:
2441 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002442 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002443 case Mips::NORImm64:
2444 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2445 case Mips::SLTImm64:
2446 if (isInt<16>(Inst.getOperand(2).getImm())) {
2447 Inst.setOpcode(Mips::SLTi64);
2448 return MER_NotAMacro;
2449 }
2450 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2451 case Mips::SLTUImm64:
2452 if (isInt<16>(Inst.getOperand(2).getImm())) {
2453 Inst.setOpcode(Mips::SLTiu64);
2454 return MER_NotAMacro;
2455 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002456 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002457 case Mips::ADDi: case Mips::ADDi_MM:
2458 case Mips::ADDiu: case Mips::ADDiu_MM:
2459 case Mips::SLTi: case Mips::SLTi_MM:
2460 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002461 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2462 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2463 int64_t ImmValue = Inst.getOperand(2).getImm();
2464 if (isInt<16>(ImmValue))
2465 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002466 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2467 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002468 }
2469 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002470 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2471 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2472 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002473 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2474 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2475 int64_t ImmValue = Inst.getOperand(2).getImm();
2476 if (isUInt<16>(ImmValue))
2477 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002478 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2479 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002480 }
2481 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002482 case Mips::ROL:
2483 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002484 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002485 case Mips::ROLImm:
2486 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002487 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002488 case Mips::DROL:
2489 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002490 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002491 case Mips::DROLImm:
2492 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002493 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002494 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002495 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002496 case Mips::MULImmMacro:
2497 case Mips::DMULImmMacro:
2498 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2499 case Mips::MULOMacro:
2500 case Mips::DMULOMacro:
2501 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2502 case Mips::MULOUMacro:
2503 case Mips::DMULOUMacro:
2504 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2505 case Mips::DMULMacro:
2506 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002507 case Mips::LDMacro:
2508 case Mips::SDMacro:
2509 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2510 Inst.getOpcode() == Mips::LDMacro)
2511 ? MER_Fail
2512 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002513 case Mips::SEQMacro:
2514 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2515 case Mips::SEQIMacro:
2516 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002517 }
Jack Carter30a59822012-10-04 04:03:53 +00002518}
Jack Carter92995f12012-10-06 00:53:28 +00002519
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002520bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002521 MCStreamer &Out,
2522 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002523 MipsTargetStreamer &TOut = getTargetStreamer();
2524
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002525 // Create a JALR instruction which is going to replace the pseudo-JAL.
2526 MCInst JalrInst;
2527 JalrInst.setLoc(IDLoc);
2528 const MCOperand FirstRegOp = Inst.getOperand(0);
2529 const unsigned Opcode = Inst.getOpcode();
2530
2531 if (Opcode == Mips::JalOneReg) {
2532 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002533 if (IsCpRestoreSet && inMicroMipsMode()) {
2534 JalrInst.setOpcode(Mips::JALRS16_MM);
2535 JalrInst.addOperand(FirstRegOp);
2536 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002537 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002538 JalrInst.addOperand(FirstRegOp);
2539 } else {
2540 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002541 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002542 JalrInst.addOperand(FirstRegOp);
2543 }
2544 } else if (Opcode == Mips::JalTwoReg) {
2545 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002546 if (IsCpRestoreSet && inMicroMipsMode())
2547 JalrInst.setOpcode(Mips::JALRS_MM);
2548 else
2549 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002550 JalrInst.addOperand(FirstRegOp);
2551 const MCOperand SecondRegOp = Inst.getOperand(1);
2552 JalrInst.addOperand(SecondRegOp);
2553 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002554 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002555
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002556 // If .set reorder is active and branch instruction has a delay slot,
2557 // emit a NOP after it.
2558 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002559 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2560 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2561 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002562
2563 return false;
2564}
2565
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002566/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002567template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002568 unsigned BitNum = findFirstSet(x);
2569
2570 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2571}
2572
2573/// Load (or add) an immediate into a register.
2574///
2575/// @param ImmValue The immediate to load.
2576/// @param DstReg The register that will hold the immediate.
2577/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2578/// for a simple initialization.
2579/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2580/// @param IsAddress True if the immediate represents an address. False if it
2581/// is an integer.
2582/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002583bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002584 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002585 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2586 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002587 MipsTargetStreamer &TOut = getTargetStreamer();
2588
Toma Tabacu00e98672015-05-01 12:19:27 +00002589 if (!Is32BitImm && !isGP64bit()) {
2590 Error(IDLoc, "instruction requires a 64-bit architecture");
2591 return true;
2592 }
2593
Daniel Sanders03f9c012015-07-14 12:24:22 +00002594 if (Is32BitImm) {
2595 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2596 // Sign extend up to 64-bit so that the predicates match the hardware
2597 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2598 // true.
2599 ImmValue = SignExtend64<32>(ImmValue);
2600 } else {
2601 Error(IDLoc, "instruction requires a 32-bit immediate");
2602 return true;
2603 }
2604 }
2605
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002606 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2607 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2608
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002609 bool UseSrcReg = false;
2610 if (SrcReg != Mips::NoRegister)
2611 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002612
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002613 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002614 if (UseSrcReg &&
2615 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002616 // At this point we need AT to perform the expansions and we exit if it is
2617 // not available.
2618 unsigned ATReg = getATReg(IDLoc);
2619 if (!ATReg)
2620 return true;
2621 TmpReg = ATReg;
2622 }
2623
Daniel Sanders03f9c012015-07-14 12:24:22 +00002624 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002625 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002626 SrcReg = ZeroReg;
2627
2628 // This doesn't quite follow the usual ABI expectations for N32 but matches
2629 // traditional assembler behaviour. N32 would normally use addiu for both
2630 // integers and addresses.
2631 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002632 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002633 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002634 }
2635
Daniel Sandersa736b372016-04-29 13:33:12 +00002636 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002637 return false;
2638 }
2639
2640 if (isUInt<16>(ImmValue)) {
2641 unsigned TmpReg = DstReg;
2642 if (SrcReg == DstReg) {
2643 TmpReg = getATReg(IDLoc);
2644 if (!TmpReg)
2645 return true;
2646 }
2647
Daniel Sandersa736b372016-04-29 13:33:12 +00002648 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002649 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002650 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002651 return false;
2652 }
2653
2654 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002655 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002656
Toma Tabacu79588102015-04-29 10:19:56 +00002657 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2658 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002659 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002660 // Traditional behaviour seems to special case this particular value. It's
2661 // not clear why other masks are handled differently.
2662 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002663 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2664 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002665 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002666 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002667 return false;
2668 }
2669
2670 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002671 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002672 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2673 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002674 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002675 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002676 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002677 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002678 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002679 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002680
Daniel Sandersa736b372016-04-29 13:33:12 +00002681 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002682 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002683 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002684 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002685 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002686 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002687 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002688
2689 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2690 if (Is32BitImm) {
2691 Error(IDLoc, "instruction requires a 32-bit immediate");
2692 return true;
2693 }
2694
2695 // Traditionally, these immediates are shifted as little as possible and as
2696 // such we align the most significant bit to bit 15 of our temporary.
2697 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2698 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2699 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2700 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002701 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2702 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002703
2704 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002705 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002706
2707 return false;
2708 }
2709
2710 warnIfNoMacro(IDLoc);
2711
2712 // The remaining case is packed with a sequence of dsll and ori with zeros
2713 // being omitted and any neighbouring dsll's being coalesced.
2714 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2715
2716 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2717 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002718 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002719 return false;
2720
2721 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2722 // skip it and defer the shift to the next chunk.
2723 unsigned ShiftCarriedForwards = 16;
2724 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2725 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2726
2727 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002728 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2729 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002730 ShiftCarriedForwards = 0;
2731 }
2732
2733 ShiftCarriedForwards += 16;
2734 }
2735 ShiftCarriedForwards -= 16;
2736
2737 // Finish any remaining shifts left by trailing zeros.
2738 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002739 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002740
2741 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002742 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002743
Matheus Almeida3813d572014-06-19 14:39:14 +00002744 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002745}
Jack Carter92995f12012-10-06 00:53:28 +00002746
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002747bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002748 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002749 const MCOperand &ImmOp = Inst.getOperand(1);
2750 assert(ImmOp.isImm() && "expected immediate operand kind");
2751 const MCOperand &DstRegOp = Inst.getOperand(0);
2752 assert(DstRegOp.isReg() && "expected register operand kind");
2753
2754 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002755 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002756 return true;
2757
2758 return false;
2759}
2760
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002761bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2762 const MCOperand &Offset,
2763 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002764 MCStreamer &Out,
2765 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002766 // la can't produce a usable address when addresses are 64-bit.
2767 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2768 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2769 // We currently can't do this because we depend on the equality
2770 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2771 Error(IDLoc, "la used to load 64-bit address");
2772 // Continue as if we had 'dla' instead.
2773 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002774 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002775 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002776
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002777 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002778 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002779 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002780 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002781 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002782
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002783 if (!Offset.isImm())
2784 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002785 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002786
Scott Egerton24557012016-01-21 15:11:01 +00002787 if (!ABI.ArePtrs64bit()) {
2788 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2789 Is32BitAddress = true;
2790 }
2791
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002792 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002793 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002794}
2795
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002796bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2797 unsigned DstReg, unsigned SrcReg,
2798 bool Is32BitSym, SMLoc IDLoc,
2799 MCStreamer &Out,
2800 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002801 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002802 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002803 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002804 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002805
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002806 if (inPicMode() && ABI.IsO32()) {
2807 MCValue Res;
2808 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2809 Error(IDLoc, "expected relocatable expression");
2810 return true;
2811 }
2812 if (Res.getSymB() != nullptr) {
2813 Error(IDLoc, "expected relocatable expression with only one symbol");
2814 return true;
2815 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002816
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002817 // The case where the result register is $25 is somewhat special. If the
2818 // symbol in the final relocation is external and not modified with a
2819 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2820 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002821 Res.getConstant() == 0 &&
2822 !(Res.getSymA()->getSymbol().isInSection() ||
2823 Res.getSymA()->getSymbol().isTemporary() ||
2824 (Res.getSymA()->getSymbol().isELF() &&
2825 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2826 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002827 const MCExpr *CallExpr =
2828 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2829 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2830 MCOperand::createExpr(CallExpr), IDLoc, STI);
2831 return false;
2832 }
2833
2834 // The remaining cases are:
2835 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2836 // >addiu $tmp, $tmp, %lo(offset)
2837 // >addiu $rd, $tmp, $rs
2838 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2839 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2840 // >addiu $rd, $tmp, $rs
2841 // The addiu's marked with a '>' may be omitted if they are redundant. If
2842 // this happens then the last instruction must use $rd as the result
2843 // register.
2844 const MipsMCExpr *GotExpr =
2845 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2846 const MCExpr *LoExpr = nullptr;
2847 if (Res.getSymA()->getSymbol().isInSection() ||
2848 Res.getSymA()->getSymbol().isTemporary())
2849 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2850 else if (Res.getConstant() != 0) {
2851 // External symbols fully resolve the symbol with just the %got(symbol)
2852 // but we must still account for any offset to the symbol for expressions
2853 // like symbol+8.
2854 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2855 }
2856
2857 unsigned TmpReg = DstReg;
2858 if (UseSrcReg &&
2859 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2860 SrcReg)) {
2861 // If $rs is the same as $rd, we need to use AT.
2862 // If it is not available we exit.
2863 unsigned ATReg = getATReg(IDLoc);
2864 if (!ATReg)
2865 return true;
2866 TmpReg = ATReg;
2867 }
2868
2869 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2870 MCOperand::createExpr(GotExpr), IDLoc, STI);
2871
2872 if (LoExpr)
2873 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2874 IDLoc, STI);
2875
2876 if (UseSrcReg)
2877 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2878
2879 return false;
2880 }
2881
Simon Dardisda96c432017-06-30 15:44:27 +00002882 if (inPicMode() && ABI.ArePtrs64bit()) {
2883 MCValue Res;
2884 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2885 Error(IDLoc, "expected relocatable expression");
2886 return true;
2887 }
2888 if (Res.getSymB() != nullptr) {
2889 Error(IDLoc, "expected relocatable expression with only one symbol");
2890 return true;
2891 }
2892
2893 // The case where the result register is $25 is somewhat special. If the
2894 // symbol in the final relocation is external and not modified with a
2895 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2896 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2897 Res.getConstant() == 0 &&
2898 !(Res.getSymA()->getSymbol().isInSection() ||
2899 Res.getSymA()->getSymbol().isTemporary() ||
2900 (Res.getSymA()->getSymbol().isELF() &&
2901 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2902 ELF::STB_LOCAL))) {
2903 const MCExpr *CallExpr =
2904 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2905 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2906 MCOperand::createExpr(CallExpr), IDLoc, STI);
2907 return false;
2908 }
2909
2910 // The remaining cases are:
2911 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2912 // >daddiu $tmp, $tmp, offset
2913 // >daddu $rd, $tmp, $rs
2914 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2915 // this happens then the last instruction must use $rd as the result
2916 // register.
2917 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2918 Res.getSymA(),
2919 getContext());
2920 const MCExpr *LoExpr = nullptr;
2921 if (Res.getConstant() != 0) {
2922 // Symbols fully resolve with just the %got_disp(symbol) but we
2923 // must still account for any offset to the symbol for
2924 // expressions like symbol+8.
2925 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2926
2927 // FIXME: Offsets greater than 16 bits are not yet implemented.
2928 // FIXME: The correct range is a 32-bit sign-extended number.
2929 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2930 Error(IDLoc, "macro instruction uses large offset, which is not "
2931 "currently supported");
2932 return true;
2933 }
2934 }
2935
2936 unsigned TmpReg = DstReg;
2937 if (UseSrcReg &&
2938 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2939 SrcReg)) {
2940 // If $rs is the same as $rd, we need to use AT.
2941 // If it is not available we exit.
2942 unsigned ATReg = getATReg(IDLoc);
2943 if (!ATReg)
2944 return true;
2945 TmpReg = ATReg;
2946 }
2947
2948 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
2949 MCOperand::createExpr(GotExpr), IDLoc, STI);
2950
2951 if (LoExpr)
2952 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2953 IDLoc, STI);
2954
2955 if (UseSrcReg)
2956 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2957
2958 return false;
2959 }
2960
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002961 const MipsMCExpr *HiExpr =
2962 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2963 const MipsMCExpr *LoExpr =
2964 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002965
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002966 // This is the 64-bit symbol address expansion.
2967 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00002968 // We need AT for the 64-bit expansion in the cases where the optional
2969 // source register is the destination register and for the superscalar
2970 // scheduled form.
2971 //
2972 // If it is not available we exit if the destination is the same as the
2973 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002974
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002975 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002976 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002977 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002978 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002979
Simon Dardis3aa8a902017-02-06 12:43:46 +00002980 bool RdRegIsRsReg =
2981 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
2982
2983 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
2984 unsigned ATReg = getATReg(IDLoc);
2985
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002986 // If $rs is the same as $rd:
2987 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2988 // daddiu $at, $at, %higher(sym)
2989 // dsll $at, $at, 16
2990 // daddiu $at, $at, %hi(sym)
2991 // dsll $at, $at, 16
2992 // daddiu $at, $at, %lo(sym)
2993 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002994 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2995 STI);
2996 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2997 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2998 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2999 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3000 IDLoc, STI);
3001 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3002 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3003 IDLoc, STI);
3004 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003005
3006 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00003007 } else if (canUseATReg() && !RdRegIsRsReg) {
3008 unsigned ATReg = getATReg(IDLoc);
3009
3010 // If the $rs is different from $rd or if $rs isn't specified and we
3011 // have $at available:
3012 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3013 // lui $at, %hi(sym)
3014 // daddiu $rd, $rd, %higher(sym)
3015 // daddiu $at, $at, %lo(sym)
3016 // dsll32 $rd, $rd, 0
3017 // daddu $rd, $rd, $at
3018 // (daddu $rd, $rd, $rs)
3019 //
3020 // Which is preferred for superscalar issue.
3021 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3022 STI);
3023 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3024 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3025 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3026 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3027 IDLoc, STI);
3028 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3029 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3030 if (UseSrcReg)
3031 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3032
3033 return false;
3034 } else if (!canUseATReg() && !RdRegIsRsReg) {
3035 // Otherwise, synthesize the address in the destination register
3036 // serially:
3037 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3038 // daddiu $rd, $rd, %higher(sym)
3039 // dsll $rd, $rd, 16
3040 // daddiu $rd, $rd, %hi(sym)
3041 // dsll $rd, $rd, 16
3042 // daddiu $rd, $rd, %lo(sym)
3043 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3044 STI);
3045 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3046 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3047 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3048 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3049 MCOperand::createExpr(HiExpr), IDLoc, STI);
3050 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3051 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3052 MCOperand::createExpr(LoExpr), IDLoc, STI);
3053 if (UseSrcReg)
3054 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3055
3056 return false;
3057 } else {
3058 // We have a case where SrcReg == DstReg and we don't have $at
3059 // available. We can't expand this case, so error out appropriately.
3060 assert(SrcReg == DstReg && !canUseATReg() &&
3061 "Could have expanded dla but didn't?");
3062 reportParseError(IDLoc,
3063 "pseudo-instruction requires $at, which is not available");
3064 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003065 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003066 }
3067
3068 // And now, the 32-bit symbol address expansion:
3069 // If $rs is the same as $rd:
3070 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3071 // ori $at, $at, %lo(sym)
3072 // addu $rd, $at, $rd
3073 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3074 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3075 // ori $rd, $rd, %lo(sym)
3076 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003077 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003078 if (UseSrcReg &&
3079 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003080 // If $rs is the same as $rd, we need to use AT.
3081 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003082 unsigned ATReg = getATReg(IDLoc);
3083 if (!ATReg)
3084 return true;
3085 TmpReg = ATReg;
3086 }
3087
Daniel Sandersa736b372016-04-29 13:33:12 +00003088 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3089 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3090 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003091
Toma Tabacufb9d1252015-06-22 12:08:39 +00003092 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003093 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003094 else
Scott Egerton24557012016-01-21 15:11:01 +00003095 assert(
3096 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003097
Toma Tabacu674825c2015-06-16 12:16:24 +00003098 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003099}
3100
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003101// Each double-precision register DO-D15 overlaps with two of the single
3102// precision registers F0-F31. As an example, all of the following hold true:
3103// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3104static unsigned nextReg(unsigned Reg) {
3105 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3106 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3107 switch (Reg) {
3108 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3109 case Mips::ZERO: return Mips::AT;
3110 case Mips::AT: return Mips::V0;
3111 case Mips::V0: return Mips::V1;
3112 case Mips::V1: return Mips::A0;
3113 case Mips::A0: return Mips::A1;
3114 case Mips::A1: return Mips::A2;
3115 case Mips::A2: return Mips::A3;
3116 case Mips::A3: return Mips::T0;
3117 case Mips::T0: return Mips::T1;
3118 case Mips::T1: return Mips::T2;
3119 case Mips::T2: return Mips::T3;
3120 case Mips::T3: return Mips::T4;
3121 case Mips::T4: return Mips::T5;
3122 case Mips::T5: return Mips::T6;
3123 case Mips::T6: return Mips::T7;
3124 case Mips::T7: return Mips::S0;
3125 case Mips::S0: return Mips::S1;
3126 case Mips::S1: return Mips::S2;
3127 case Mips::S2: return Mips::S3;
3128 case Mips::S3: return Mips::S4;
3129 case Mips::S4: return Mips::S5;
3130 case Mips::S5: return Mips::S6;
3131 case Mips::S6: return Mips::S7;
3132 case Mips::S7: return Mips::T8;
3133 case Mips::T8: return Mips::T9;
3134 case Mips::T9: return Mips::K0;
3135 case Mips::K0: return Mips::K1;
3136 case Mips::K1: return Mips::GP;
3137 case Mips::GP: return Mips::SP;
3138 case Mips::SP: return Mips::FP;
3139 case Mips::FP: return Mips::RA;
3140 case Mips::RA: return Mips::ZERO;
3141 case Mips::D0: return Mips::F1;
3142 case Mips::D1: return Mips::F3;
3143 case Mips::D2: return Mips::F5;
3144 case Mips::D3: return Mips::F7;
3145 case Mips::D4: return Mips::F9;
3146 case Mips::D5: return Mips::F11;
3147 case Mips::D6: return Mips::F13;
3148 case Mips::D7: return Mips::F15;
3149 case Mips::D8: return Mips::F17;
3150 case Mips::D9: return Mips::F19;
3151 case Mips::D10: return Mips::F21;
3152 case Mips::D11: return Mips::F23;
3153 case Mips::D12: return Mips::F25;
3154 case Mips::D13: return Mips::F27;
3155 case Mips::D14: return Mips::F29;
3156 case Mips::D15: return Mips::F31;
3157 }
3158}
3159
3160// FIXME: This method is too general. In principle we should compute the number
3161// of instructions required to synthesize the immediate inline compared to
3162// synthesizing the address inline and relying on non .text sections.
3163// For static O32 and N32 this may yield a small benefit, for static N64 this is
3164// likely to yield a much larger benefit as we have to synthesize a 64bit
3165// address to load a 64 bit value.
3166bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3167 MCSymbol *Sym) {
3168 unsigned ATReg = getATReg(IDLoc);
3169 if (!ATReg)
3170 return true;
3171
3172 if(IsPicEnabled) {
3173 const MCExpr *GotSym =
3174 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3175 const MipsMCExpr *GotExpr =
3176 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3177
3178 if(isABI_O32() || isABI_N32()) {
3179 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3180 IDLoc, STI);
3181 } else { //isABI_N64()
3182 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3183 IDLoc, STI);
3184 }
3185 } else { //!IsPicEnabled
3186 const MCExpr *HiSym =
3187 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3188 const MipsMCExpr *HiExpr =
3189 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3190
3191 // FIXME: This is technically correct but gives a different result to gas,
3192 // but gas is incomplete there (it has a fixme noting it doesn't work with
3193 // 64-bit addresses).
3194 // FIXME: With -msym32 option, the address expansion for N64 should probably
3195 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3196 // symbol's value is considered sign extended.
3197 if(isABI_O32() || isABI_N32()) {
3198 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3199 } else { //isABI_N64()
3200 const MCExpr *HighestSym =
3201 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3202 const MipsMCExpr *HighestExpr =
3203 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3204 const MCExpr *HigherSym =
3205 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3206 const MipsMCExpr *HigherExpr =
3207 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3208
3209 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3210 STI);
3211 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3212 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3213 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3214 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3215 IDLoc, STI);
3216 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3217 }
3218 }
3219 return false;
3220}
3221
3222bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3223 bool Is64FPU, SMLoc IDLoc,
3224 MCStreamer &Out,
3225 const MCSubtargetInfo *STI) {
3226 MipsTargetStreamer &TOut = getTargetStreamer();
3227 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3228 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3229 "Invalid instruction operand.");
3230
3231 unsigned FirstReg = Inst.getOperand(0).getReg();
3232 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3233
3234 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3235 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3236 // exponent field), convert it to double (e.g. 1 to 1.0)
3237 if ((HiImmOp64 & 0x7ff00000) == 0) {
3238 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3239 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3240 }
3241
3242 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3243 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3244
3245 if (IsSingle) {
3246 // Conversion of a double in an uint64_t to a float in a uint32_t,
3247 // retaining the bit pattern of a float.
3248 uint32_t ImmOp32;
3249 double doubleImm = BitsToDouble(ImmOp64);
3250 float tmp_float = static_cast<float>(doubleImm);
3251 ImmOp32 = FloatToBits(tmp_float);
3252
3253 if (IsGPR) {
3254 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3255 Out, STI))
3256 return true;
3257 return false;
3258 } else {
3259 unsigned ATReg = getATReg(IDLoc);
3260 if (!ATReg)
3261 return true;
3262 if (LoImmOp64 == 0) {
3263 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3264 Out, STI))
3265 return true;
3266 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3267 return false;
3268 }
3269
3270 MCSection *CS = getStreamer().getCurrentSectionOnly();
3271 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3272 // where appropriate.
3273 MCSection *ReadOnlySection = getContext().getELFSection(
3274 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3275
3276 MCSymbol *Sym = getContext().createTempSymbol();
3277 const MCExpr *LoSym =
3278 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3279 const MipsMCExpr *LoExpr =
3280 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3281
3282 getStreamer().SwitchSection(ReadOnlySection);
3283 getStreamer().EmitLabel(Sym, IDLoc);
3284 getStreamer().EmitIntValue(ImmOp32, 4);
3285 getStreamer().SwitchSection(CS);
3286
3287 if(emitPartialAddress(TOut, IDLoc, Sym))
3288 return true;
3289 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3290 MCOperand::createExpr(LoExpr), IDLoc, STI);
3291 }
3292 return false;
3293 }
3294
3295 // if(!IsSingle)
3296 unsigned ATReg = getATReg(IDLoc);
3297 if (!ATReg)
3298 return true;
3299
3300 if (IsGPR) {
3301 if (LoImmOp64 == 0) {
3302 if(isABI_N32() || isABI_N64()) {
3303 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3304 IDLoc, Out, STI))
3305 return true;
3306 return false;
3307 } else {
3308 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3309 IDLoc, Out, STI))
3310 return true;
3311
3312 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3313 IDLoc, Out, STI))
3314 return true;
3315 return false;
3316 }
3317 }
3318
3319 MCSection *CS = getStreamer().getCurrentSectionOnly();
3320 MCSection *ReadOnlySection = getContext().getELFSection(
3321 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3322
3323 MCSymbol *Sym = getContext().createTempSymbol();
3324 const MCExpr *LoSym =
3325 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3326 const MipsMCExpr *LoExpr =
3327 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3328
3329 getStreamer().SwitchSection(ReadOnlySection);
3330 getStreamer().EmitLabel(Sym, IDLoc);
3331 getStreamer().EmitIntValue(HiImmOp64, 4);
3332 getStreamer().EmitIntValue(LoImmOp64, 4);
3333 getStreamer().SwitchSection(CS);
3334
3335 if(emitPartialAddress(TOut, IDLoc, Sym))
3336 return true;
3337 if(isABI_N64())
3338 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3339 MCOperand::createExpr(LoExpr), IDLoc, STI);
3340 else
3341 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3342 MCOperand::createExpr(LoExpr), IDLoc, STI);
3343
3344 if(isABI_N32() || isABI_N64())
3345 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3346 else {
3347 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3348 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3349 }
3350 return false;
3351 } else { // if(!IsGPR && !IsSingle)
3352 if ((LoImmOp64 == 0) &&
3353 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3354 // FIXME: In the case where the constant is zero, we can load the
3355 // register directly from the zero register.
3356 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3357 Out, STI))
3358 return true;
3359 if (isABI_N32() || isABI_N64())
3360 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3361 else if (hasMips32r2()) {
3362 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3363 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3364 } else {
3365 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3366 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3367 }
3368 return false;
3369 }
3370
3371 MCSection *CS = getStreamer().getCurrentSectionOnly();
3372 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3373 // where appropriate.
3374 MCSection *ReadOnlySection = getContext().getELFSection(
3375 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3376
3377 MCSymbol *Sym = getContext().createTempSymbol();
3378 const MCExpr *LoSym =
3379 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3380 const MipsMCExpr *LoExpr =
3381 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3382
3383 getStreamer().SwitchSection(ReadOnlySection);
3384 getStreamer().EmitLabel(Sym, IDLoc);
3385 getStreamer().EmitIntValue(HiImmOp64, 4);
3386 getStreamer().EmitIntValue(LoImmOp64, 4);
3387 getStreamer().SwitchSection(CS);
3388
3389 if(emitPartialAddress(TOut, IDLoc, Sym))
3390 return true;
3391 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3392 MCOperand::createExpr(LoExpr), IDLoc, STI);
3393 }
3394 return false;
3395}
3396
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003397bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3398 MCStreamer &Out,
3399 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003400 MipsTargetStreamer &TOut = getTargetStreamer();
3401
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003402 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3403 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003404
3405 MCOperand Offset = Inst.getOperand(0);
3406 if (Offset.isExpr()) {
3407 Inst.clear();
3408 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003409 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3410 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3411 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003412 } else {
3413 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003414 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003415 // If offset fits into 11 bits then this instruction becomes microMIPS
3416 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003417 if (inMicroMipsMode())
3418 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003419 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003420 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003421 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003422 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003423 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003424 Inst.clear();
3425 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003426 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3427 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3428 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003429 }
3430 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003431 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003432
Zoran Jovanovicada70912015-09-07 11:56:37 +00003433 // If .set reorder is active and branch instruction has a delay slot,
3434 // emit a NOP after it.
3435 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3436 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003437 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003438
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003439 return false;
3440}
3441
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003442bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3443 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003444 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003445 const MCOperand &DstRegOp = Inst.getOperand(0);
3446 assert(DstRegOp.isReg() && "expected register operand kind");
3447
3448 const MCOperand &ImmOp = Inst.getOperand(1);
3449 assert(ImmOp.isImm() && "expected immediate operand kind");
3450
3451 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003452 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3453 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003454
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003455 bool IsLikely = false;
3456
Toma Tabacue1e460d2015-06-11 10:36:10 +00003457 unsigned OpCode = 0;
3458 switch(Inst.getOpcode()) {
3459 case Mips::BneImm:
3460 OpCode = Mips::BNE;
3461 break;
3462 case Mips::BeqImm:
3463 OpCode = Mips::BEQ;
3464 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003465 case Mips::BEQLImmMacro:
3466 OpCode = Mips::BEQL;
3467 IsLikely = true;
3468 break;
3469 case Mips::BNELImmMacro:
3470 OpCode = Mips::BNEL;
3471 IsLikely = true;
3472 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003473 default:
3474 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3475 break;
3476 }
3477
3478 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003479 if (ImmValue == 0) {
3480 if (IsLikely) {
3481 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3482 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3483 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3484 } else
3485 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3486 STI);
3487 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003488 warnIfNoMacro(IDLoc);
3489
3490 unsigned ATReg = getATReg(IDLoc);
3491 if (!ATReg)
3492 return true;
3493
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003494 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003495 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003496 return true;
3497
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003498 if (IsLikely) {
3499 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3500 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3501 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3502 } else
3503 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003504 }
3505 return false;
3506}
3507
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003508void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00003509 const MCSubtargetInfo *STI, bool IsLoad,
3510 bool IsImmOpnd) {
3511 if (IsLoad) {
3512 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3513 return;
Scott Egertond65377d2016-03-17 10:37:51 +00003514 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003515 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3516}
3517
3518void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3519 const MCSubtargetInfo *STI, bool IsImmOpnd) {
3520 MipsTargetStreamer &TOut = getTargetStreamer();
3521
3522 unsigned DstReg = Inst.getOperand(0).getReg();
3523 unsigned BaseReg = Inst.getOperand(1).getReg();
3524
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003525 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003526 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3527 unsigned DstRegClassID =
3528 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3529 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3530 (DstRegClassID == Mips::GPR64RegClassID);
3531
3532 if (IsImmOpnd) {
3533 // Try to use DstReg as the temporary.
3534 if (IsGPR && (BaseReg != DstReg)) {
3535 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3536 Inst.getOperand(2).getImm(), DstReg, IDLoc,
3537 STI);
3538 return;
3539 }
3540
Matheus Almeida7de68e72014-06-18 14:46:05 +00003541 // At this point we need AT to perform the expansions and we exit if it is
3542 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00003543 unsigned ATReg = getATReg(IDLoc);
3544 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00003545 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003546
3547 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3548 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
3549 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00003550 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00003551
Daniel Sandersfba875f2016-04-29 13:43:45 +00003552 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003553 MCOperand LoOperand = MCOperand::createExpr(
3554 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3555 MCOperand HiOperand = MCOperand::createExpr(
3556 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003557
3558 // Try to use DstReg as the temporary.
3559 if (IsGPR && (BaseReg != DstReg)) {
3560 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3561 LoOperand, DstReg, IDLoc, STI);
3562 return;
3563 }
3564
3565 // At this point we need AT to perform the expansions and we exit if it is
3566 // not available.
3567 unsigned ATReg = getATReg(IDLoc);
3568 if (!ATReg)
3569 return;
3570
3571 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3572 LoOperand, ATReg, IDLoc, STI);
3573}
3574
3575void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3576 const MCSubtargetInfo *STI,
3577 bool IsImmOpnd) {
3578 MipsTargetStreamer &TOut = getTargetStreamer();
3579
3580 unsigned SrcReg = Inst.getOperand(0).getReg();
3581 unsigned BaseReg = Inst.getOperand(1).getReg();
3582
Daniel Sanders241c6792016-05-12 14:01:50 +00003583 if (IsImmOpnd) {
3584 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
3585 Inst.getOperand(2).getImm(),
3586 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3587 return;
3588 }
3589
Daniel Sandersfba875f2016-04-29 13:43:45 +00003590 unsigned ATReg = getATReg(IDLoc);
3591 if (!ATReg)
3592 return;
3593
Daniel Sandersfba875f2016-04-29 13:43:45 +00003594 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003595 MCOperand LoOperand = MCOperand::createExpr(
3596 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3597 MCOperand HiOperand = MCOperand::createExpr(
3598 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003599 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3600 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003601}
3602
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003603bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3604 MCStreamer &Out,
3605 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003606 unsigned OpNum = Inst.getNumOperands();
3607 unsigned Opcode = Inst.getOpcode();
3608 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3609
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003610 assert(Inst.getOperand(OpNum - 1).isImm() &&
3611 Inst.getOperand(OpNum - 2).isReg() &&
3612 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003613
3614 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3615 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003616 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3617 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3618 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3619 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003620 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003621 if (inMicroMipsMode() && hasMips32r6())
3622 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3623 else
3624 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3625 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003626
3627 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003628 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003629 return false;
3630}
3631
Toma Tabacu1a108322015-06-17 13:20:24 +00003632bool MipsAsmParser::expandCondBranches(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();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003636 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003637 unsigned PseudoOpcode = Inst.getOpcode();
3638 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003639 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003640 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3641
3642 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003643 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003644
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003645 unsigned TrgReg;
3646 if (TrgOp.isReg())
3647 TrgReg = TrgOp.getReg();
3648 else if (TrgOp.isImm()) {
3649 warnIfNoMacro(IDLoc);
3650 EmittedNoMacroWarning = true;
3651
3652 TrgReg = getATReg(IDLoc);
3653 if (!TrgReg)
3654 return true;
3655
3656 switch(PseudoOpcode) {
3657 default:
3658 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3659 case Mips::BLTImmMacro:
3660 PseudoOpcode = Mips::BLT;
3661 break;
3662 case Mips::BLEImmMacro:
3663 PseudoOpcode = Mips::BLE;
3664 break;
3665 case Mips::BGEImmMacro:
3666 PseudoOpcode = Mips::BGE;
3667 break;
3668 case Mips::BGTImmMacro:
3669 PseudoOpcode = Mips::BGT;
3670 break;
3671 case Mips::BLTUImmMacro:
3672 PseudoOpcode = Mips::BLTU;
3673 break;
3674 case Mips::BLEUImmMacro:
3675 PseudoOpcode = Mips::BLEU;
3676 break;
3677 case Mips::BGEUImmMacro:
3678 PseudoOpcode = Mips::BGEU;
3679 break;
3680 case Mips::BGTUImmMacro:
3681 PseudoOpcode = Mips::BGTU;
3682 break;
3683 case Mips::BLTLImmMacro:
3684 PseudoOpcode = Mips::BLTL;
3685 break;
3686 case Mips::BLELImmMacro:
3687 PseudoOpcode = Mips::BLEL;
3688 break;
3689 case Mips::BGELImmMacro:
3690 PseudoOpcode = Mips::BGEL;
3691 break;
3692 case Mips::BGTLImmMacro:
3693 PseudoOpcode = Mips::BGTL;
3694 break;
3695 case Mips::BLTULImmMacro:
3696 PseudoOpcode = Mips::BLTUL;
3697 break;
3698 case Mips::BLEULImmMacro:
3699 PseudoOpcode = Mips::BLEUL;
3700 break;
3701 case Mips::BGEULImmMacro:
3702 PseudoOpcode = Mips::BGEUL;
3703 break;
3704 case Mips::BGTULImmMacro:
3705 PseudoOpcode = Mips::BGTUL;
3706 break;
3707 }
3708
3709 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003710 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003711 return true;
3712 }
3713
Toma Tabacu1a108322015-06-17 13:20:24 +00003714 switch (PseudoOpcode) {
3715 case Mips::BLT:
3716 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003717 case Mips::BLTL:
3718 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003719 AcceptsEquality = false;
3720 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003721 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3722 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003723 ZeroSrcOpcode = Mips::BGTZ;
3724 ZeroTrgOpcode = Mips::BLTZ;
3725 break;
3726 case Mips::BLE:
3727 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003728 case Mips::BLEL:
3729 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003730 AcceptsEquality = true;
3731 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003732 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3733 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003734 ZeroSrcOpcode = Mips::BGEZ;
3735 ZeroTrgOpcode = Mips::BLEZ;
3736 break;
3737 case Mips::BGE:
3738 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003739 case Mips::BGEL:
3740 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003741 AcceptsEquality = true;
3742 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003743 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3744 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003745 ZeroSrcOpcode = Mips::BLEZ;
3746 ZeroTrgOpcode = Mips::BGEZ;
3747 break;
3748 case Mips::BGT:
3749 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003750 case Mips::BGTL:
3751 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003752 AcceptsEquality = false;
3753 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003754 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3755 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003756 ZeroSrcOpcode = Mips::BLTZ;
3757 ZeroTrgOpcode = Mips::BGTZ;
3758 break;
3759 default:
3760 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3761 }
3762
Toma Tabacu1a108322015-06-17 13:20:24 +00003763 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3764 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3765 if (IsSrcRegZero && IsTrgRegZero) {
3766 // FIXME: All of these Opcode-specific if's are needed for compatibility
3767 // with GAS' behaviour. However, they may not generate the most efficient
3768 // code in some circumstances.
3769 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003770 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3771 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003772 return false;
3773 }
3774 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003775 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3776 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003777 Warning(IDLoc, "branch is always taken");
3778 return false;
3779 }
3780 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003781 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3782 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003783 Warning(IDLoc, "branch is always taken");
3784 return false;
3785 }
3786 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003787 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3788 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003789 return false;
3790 }
3791 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003792 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3793 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003794 return false;
3795 }
3796 if (AcceptsEquality) {
3797 // If both registers are $0 and the pseudo-branch accepts equality, it
3798 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003799 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3800 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003801 Warning(IDLoc, "branch is always taken");
3802 return false;
3803 }
3804 // If both registers are $0 and the pseudo-branch does not accept
3805 // equality, it will never be taken, so we don't have to emit anything.
3806 return false;
3807 }
3808 if (IsSrcRegZero || IsTrgRegZero) {
3809 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3810 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3811 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3812 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3813 // the pseudo-branch will never be taken, so we don't emit anything.
3814 // This only applies to unsigned pseudo-branches.
3815 return false;
3816 }
3817 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3818 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3819 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3820 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3821 // the pseudo-branch will always be taken, so we emit an unconditional
3822 // branch.
3823 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003824 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3825 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003826 Warning(IDLoc, "branch is always taken");
3827 return false;
3828 }
3829 if (IsUnsigned) {
3830 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3831 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3832 // the pseudo-branch will be taken only when the non-zero register is
3833 // different from 0, so we emit a BNEZ.
3834 //
3835 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3836 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3837 // the pseudo-branch will be taken only when the non-zero register is
3838 // equal to 0, so we emit a BEQZ.
3839 //
3840 // Because only BLEU and BGEU branch on equality, we can use the
3841 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003842 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3843 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3844 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003845 return false;
3846 }
3847 // If we have a signed pseudo-branch and one of the registers is $0,
3848 // we can use an appropriate compare-to-zero branch. We select which one
3849 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003850 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3851 IsSrcRegZero ? TrgReg : SrcReg,
3852 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003853 return false;
3854 }
3855
3856 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3857 // expansions. If it is not available, we return.
3858 unsigned ATRegNum = getATReg(IDLoc);
3859 if (!ATRegNum)
3860 return true;
3861
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003862 if (!EmittedNoMacroWarning)
3863 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003864
3865 // SLT fits well with 2 of our 4 pseudo-branches:
3866 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3867 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3868 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3869 // This is accomplished by using a BNEZ with the result of the SLT.
3870 //
3871 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3872 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3873 // Because only BGE and BLE branch on equality, we can use the
3874 // AcceptsEquality variable to decide when to emit the BEQZ.
3875 // Note that the order of the SLT arguments doesn't change between
3876 // opposites.
3877 //
3878 // The same applies to the unsigned variants, except that SLTu is used
3879 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003880 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3881 ReverseOrderSLT ? TrgReg : SrcReg,
3882 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003883
Daniel Sandersa736b372016-04-29 13:33:12 +00003884 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3885 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3886 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3887 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003888 return false;
3889}
3890
Simon Dardis509da1a2017-02-13 16:06:48 +00003891// Expand a integer division macro.
3892//
3893// Notably we don't have to emit a warning when encountering $rt as the $zero
3894// register, or 0 as an immediate. processInstruction() has already done that.
3895//
3896// The destination register can only be $zero when expanding (S)DivIMacro or
3897// D(S)DivMacro.
3898
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003899bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3900 const MCSubtargetInfo *STI, const bool IsMips64,
3901 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003902 MipsTargetStreamer &TOut = getTargetStreamer();
3903
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003904 warnIfNoMacro(IDLoc);
3905
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003906 const MCOperand &RdRegOp = Inst.getOperand(0);
3907 assert(RdRegOp.isReg() && "expected register operand kind");
3908 unsigned RdReg = RdRegOp.getReg();
3909
3910 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003911 assert(RsRegOp.isReg() && "expected register operand kind");
3912 unsigned RsReg = RsRegOp.getReg();
3913
Simon Dardis12850ee2017-01-31 10:49:24 +00003914 unsigned RtReg;
3915 int64_t ImmValue;
3916
3917 const MCOperand &RtOp = Inst.getOperand(2);
3918 assert((RtOp.isReg() || RtOp.isImm()) &&
3919 "expected register or immediate operand kind");
3920 if (RtOp.isReg())
3921 RtReg = RtOp.getReg();
3922 else
3923 ImmValue = RtOp.getImm();
3924
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003925 unsigned DivOp;
3926 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003927 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003928
3929 if (IsMips64) {
3930 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3931 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003932 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003933 } else {
3934 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3935 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003936 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003937 }
3938
3939 bool UseTraps = useTraps();
3940
Simon Dardis12850ee2017-01-31 10:49:24 +00003941 if (RtOp.isImm()) {
3942 unsigned ATReg = getATReg(IDLoc);
3943 if (!ATReg)
3944 return true;
3945
3946 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003947 if (UseTraps)
3948 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3949 else
3950 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3951 return false;
3952 }
3953
3954 if (ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003955 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003956 return false;
3957 } else if (Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003958 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003959 return false;
3960 } else {
3961 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
3962 false, Inst.getLoc(), Out, STI))
3963 return true;
3964 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
3965 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
3966 return false;
3967 }
3968 return true;
3969 }
3970
Simon Dardis509da1a2017-02-13 16:06:48 +00003971 // If the macro expansion of (d)div(u) would always trap or break, insert
3972 // the trap/break and exit. This gives a different result to GAS. GAS has
3973 // an inconsistency/missed optimization in that not all cases are handled
3974 // equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003975 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003976 if (UseTraps) {
3977 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003978 return false;
3979 }
Simon Dardis509da1a2017-02-13 16:06:48 +00003980 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3981 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003982 }
3983
Simon Dardis509da1a2017-02-13 16:06:48 +00003984 // Temporary label for first branch traget
3985 MCContext &Context = TOut.getStreamer().getContext();
3986 MCSymbol *BrTarget;
3987 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003988
3989 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003990 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003991 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003992 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00003993 BrTarget = Context.createTempSymbol();
3994 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
3995 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003996 }
3997
Daniel Sandersa736b372016-04-29 13:33:12 +00003998 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003999
4000 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004001 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004002
4003 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004004 if (!UseTraps)
4005 TOut.getStreamer().EmitLabel(BrTarget);
4006
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004007 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004008 return false;
4009 }
4010
4011 unsigned ATReg = getATReg(IDLoc);
4012 if (!ATReg)
4013 return true;
4014
Simon Dardis509da1a2017-02-13 16:06:48 +00004015 if (!UseTraps)
4016 TOut.getStreamer().EmitLabel(BrTarget);
4017
Daniel Sandersa736b372016-04-29 13:33:12 +00004018 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004019
4020 // Temporary label for the second branch target.
4021 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4022 MCOperand LabelOpEnd =
4023 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4024
4025 // Branch to the mflo instruction.
4026 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4027
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004028 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004029 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
4030 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004031 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004032 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004033 }
4034
4035 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004036 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004037 else {
4038 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004039 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004040 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
4041 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004042 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004043
4044 TOut.getStreamer().EmitLabel(BrTargetEnd);
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004045 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004046 return false;
4047}
4048
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004049bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004050 SMLoc IDLoc, MCStreamer &Out,
4051 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004052 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004053
4054 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4055 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4056 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4057
4058 unsigned FirstReg = Inst.getOperand(0).getReg();
4059 unsigned SecondReg = Inst.getOperand(1).getReg();
4060 unsigned ThirdReg = Inst.getOperand(2).getReg();
4061
4062 if (hasMips1() && !hasMips2()) {
4063 unsigned ATReg = getATReg(IDLoc);
4064 if (!ATReg)
4065 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004066 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4067 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4068 TOut.emitNop(IDLoc, STI);
4069 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4070 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4071 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4072 TOut.emitNop(IDLoc, STI);
4073 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4074 : Mips::CVT_W_S,
4075 FirstReg, SecondReg, IDLoc, STI);
4076 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4077 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004078 return false;
4079 }
4080
Daniel Sandersa736b372016-04-29 13:33:12 +00004081 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4082 : Mips::TRUNC_W_S,
4083 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004084
4085 return false;
4086}
4087
Daniel Sanders6394ee52015-10-15 14:52:58 +00004088bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004089 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004090 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004091 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004092 }
4093
Toma Tabacud88d79c2015-06-23 14:39:42 +00004094 const MCOperand &DstRegOp = Inst.getOperand(0);
4095 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004096 const MCOperand &SrcRegOp = Inst.getOperand(1);
4097 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004098 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4099 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4100
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004101 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004102 unsigned DstReg = DstRegOp.getReg();
4103 unsigned SrcReg = SrcRegOp.getReg();
4104 int64_t OffsetValue = OffsetImmOp.getImm();
4105
4106 // NOTE: We always need AT for ULHU, as it is always used as the source
4107 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004108 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004109 unsigned ATReg = getATReg(IDLoc);
4110 if (!ATReg)
4111 return true;
4112
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004113 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4114 if (IsLargeOffset) {
4115 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4116 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004117 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004118 }
4119
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004120 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4121 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4122 if (isLittle())
4123 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004124
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004125 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4126 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004127
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004128 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4129 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004130
Daniel Sandersa736b372016-04-29 13:33:12 +00004131 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004132 FirstOffset, IDLoc, STI);
4133 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004134 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004135 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004136
4137 return false;
4138}
4139
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004140bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004141 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004142 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004143 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004144 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004145
4146 const MCOperand &DstRegOp = Inst.getOperand(0);
4147 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004148 const MCOperand &SrcRegOp = Inst.getOperand(1);
4149 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004150 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4151 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4152
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004153 MipsTargetStreamer &TOut = getTargetStreamer();
4154 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004155 unsigned SrcReg = SrcRegOp.getReg();
4156 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004157
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004158 warnIfNoMacro(IDLoc);
4159 unsigned ATReg = getATReg(IDLoc);
4160 if (!ATReg)
4161 return true;
4162
4163 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4164 if (IsLargeOffset) {
4165 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4166 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004167 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004168 }
4169
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004170 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4171 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4172 if (isLittle())
4173 std::swap(FirstOffset, SecondOffset);
4174
4175 if (IsLargeOffset) {
4176 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4177 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4178 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4179 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4180 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4181 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004182 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004183 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4184 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4185 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004186 }
4187
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004188 return false;
4189}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004190
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004191bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4192 const MCSubtargetInfo *STI) {
4193 if (hasMips32r6() || hasMips64r6()) {
4194 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4195 }
4196
4197 const MCOperand &DstRegOp = Inst.getOperand(0);
4198 assert(DstRegOp.isReg() && "expected register operand kind");
4199 const MCOperand &SrcRegOp = Inst.getOperand(1);
4200 assert(SrcRegOp.isReg() && "expected register operand kind");
4201 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4202 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4203
4204 MipsTargetStreamer &TOut = getTargetStreamer();
4205 unsigned DstReg = DstRegOp.getReg();
4206 unsigned SrcReg = SrcRegOp.getReg();
4207 int64_t OffsetValue = OffsetImmOp.getImm();
4208
4209 // Compute left/right load/store offsets.
4210 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4211 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4212 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4213 if (isLittle())
4214 std::swap(LxlOffset, LxrOffset);
4215
4216 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4217 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4218 unsigned TmpReg = SrcReg;
4219 if (IsLargeOffset || DoMove) {
4220 warnIfNoMacro(IDLoc);
4221 TmpReg = getATReg(IDLoc);
4222 if (!TmpReg)
4223 return true;
4224 }
4225
4226 if (IsLargeOffset) {
4227 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4228 IDLoc, Out, STI))
4229 return true;
4230 }
4231
4232 if (DoMove)
4233 std::swap(DstReg, TmpReg);
4234
4235 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4236 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4237 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4238 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4239
4240 if (DoMove)
4241 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004242
4243 return false;
4244}
4245
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004246bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004247 MCStreamer &Out,
4248 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004249 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004250
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004251 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4252 assert(Inst.getOperand(0).isReg() &&
4253 Inst.getOperand(1).isReg() &&
4254 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004255
4256 unsigned ATReg = Mips::NoRegister;
4257 unsigned FinalDstReg = Mips::NoRegister;
4258 unsigned DstReg = Inst.getOperand(0).getReg();
4259 unsigned SrcReg = Inst.getOperand(1).getReg();
4260 int64_t ImmValue = Inst.getOperand(2).getImm();
4261
Simon Dardisaa208812017-02-24 14:34:32 +00004262 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004263
4264 unsigned FinalOpcode = Inst.getOpcode();
4265
4266 if (DstReg == SrcReg) {
4267 ATReg = getATReg(Inst.getLoc());
4268 if (!ATReg)
4269 return true;
4270 FinalDstReg = DstReg;
4271 DstReg = ATReg;
4272 }
4273
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004274 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004275 switch (FinalOpcode) {
4276 default:
4277 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004278 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004279 FinalOpcode = Mips::ADD;
4280 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004281 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004282 FinalOpcode = Mips::ADDu;
4283 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004284 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004285 FinalOpcode = Mips::AND;
4286 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004287 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004288 FinalOpcode = Mips::NOR;
4289 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004290 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004291 FinalOpcode = Mips::OR;
4292 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004293 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004294 FinalOpcode = Mips::SLT;
4295 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004296 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004297 FinalOpcode = Mips::SLTu;
4298 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004299 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004300 FinalOpcode = Mips::XOR;
4301 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004302 case Mips::ADDi_MM:
4303 FinalOpcode = Mips::ADD_MM;
4304 break;
4305 case Mips::ADDiu_MM:
4306 FinalOpcode = Mips::ADDu_MM;
4307 break;
4308 case Mips::ANDi_MM:
4309 FinalOpcode = Mips::AND_MM;
4310 break;
4311 case Mips::ORi_MM:
4312 FinalOpcode = Mips::OR_MM;
4313 break;
4314 case Mips::SLTi_MM:
4315 FinalOpcode = Mips::SLT_MM;
4316 break;
4317 case Mips::SLTiu_MM:
4318 FinalOpcode = Mips::SLTu_MM;
4319 break;
4320 case Mips::XORi_MM:
4321 FinalOpcode = Mips::XOR_MM;
4322 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004323 case Mips::ANDi64:
4324 FinalOpcode = Mips::AND64;
4325 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004326 case Mips::NORImm64:
4327 FinalOpcode = Mips::NOR64;
4328 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004329 case Mips::ORi64:
4330 FinalOpcode = Mips::OR64;
4331 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004332 case Mips::SLTImm64:
4333 FinalOpcode = Mips::SLT64;
4334 break;
4335 case Mips::SLTUImm64:
4336 FinalOpcode = Mips::SLTu64;
4337 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004338 case Mips::XORi64:
4339 FinalOpcode = Mips::XOR64;
4340 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004341 }
4342
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004343 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004344 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004345 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004346 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004347 return false;
4348 }
4349 return true;
4350}
4351
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004352bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4353 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004354 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004355 unsigned ATReg = Mips::NoRegister;
4356 unsigned DReg = Inst.getOperand(0).getReg();
4357 unsigned SReg = Inst.getOperand(1).getReg();
4358 unsigned TReg = Inst.getOperand(2).getReg();
4359 unsigned TmpReg = DReg;
4360
4361 unsigned FirstShift = Mips::NOP;
4362 unsigned SecondShift = Mips::NOP;
4363
4364 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004365 if (DReg == SReg) {
4366 TmpReg = getATReg(Inst.getLoc());
4367 if (!TmpReg)
4368 return true;
4369 }
4370
4371 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004372 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4373 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004374 return false;
4375 }
4376
4377 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004378 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004379 return false;
4380 }
4381
4382 return true;
4383 }
4384
4385 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004386 switch (Inst.getOpcode()) {
4387 default:
4388 llvm_unreachable("unexpected instruction opcode");
4389 case Mips::ROL:
4390 FirstShift = Mips::SRLV;
4391 SecondShift = Mips::SLLV;
4392 break;
4393 case Mips::ROR:
4394 FirstShift = Mips::SLLV;
4395 SecondShift = Mips::SRLV;
4396 break;
4397 }
4398
4399 ATReg = getATReg(Inst.getLoc());
4400 if (!ATReg)
4401 return true;
4402
Daniel Sandersa736b372016-04-29 13:33:12 +00004403 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4404 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4405 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4406 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004407
4408 return false;
4409 }
4410
4411 return true;
4412}
4413
4414bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004415 MCStreamer &Out,
4416 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004417 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004418 unsigned ATReg = Mips::NoRegister;
4419 unsigned DReg = Inst.getOperand(0).getReg();
4420 unsigned SReg = Inst.getOperand(1).getReg();
4421 int64_t ImmValue = Inst.getOperand(2).getImm();
4422
4423 unsigned FirstShift = Mips::NOP;
4424 unsigned SecondShift = Mips::NOP;
4425
4426 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004427 if (Inst.getOpcode() == Mips::ROLImm) {
4428 uint64_t MaxShift = 32;
4429 uint64_t ShiftValue = ImmValue;
4430 if (ImmValue != 0)
4431 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004432 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004433 return false;
4434 }
4435
4436 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004437 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004438 return false;
4439 }
4440
4441 return true;
4442 }
4443
4444 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004445 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004446 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004447 return false;
4448 }
4449
4450 switch (Inst.getOpcode()) {
4451 default:
4452 llvm_unreachable("unexpected instruction opcode");
4453 case Mips::ROLImm:
4454 FirstShift = Mips::SLL;
4455 SecondShift = Mips::SRL;
4456 break;
4457 case Mips::RORImm:
4458 FirstShift = Mips::SRL;
4459 SecondShift = Mips::SLL;
4460 break;
4461 }
4462
4463 ATReg = getATReg(Inst.getLoc());
4464 if (!ATReg)
4465 return true;
4466
Daniel Sandersa736b372016-04-29 13:33:12 +00004467 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4468 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4469 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004470
4471 return false;
4472 }
4473
4474 return true;
4475}
4476
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004477bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4478 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004479 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004480 unsigned ATReg = Mips::NoRegister;
4481 unsigned DReg = Inst.getOperand(0).getReg();
4482 unsigned SReg = Inst.getOperand(1).getReg();
4483 unsigned TReg = Inst.getOperand(2).getReg();
4484 unsigned TmpReg = DReg;
4485
4486 unsigned FirstShift = Mips::NOP;
4487 unsigned SecondShift = Mips::NOP;
4488
4489 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004490 if (TmpReg == SReg) {
4491 TmpReg = getATReg(Inst.getLoc());
4492 if (!TmpReg)
4493 return true;
4494 }
4495
4496 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004497 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4498 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004499 return false;
4500 }
4501
4502 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004503 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004504 return false;
4505 }
4506
4507 return true;
4508 }
4509
4510 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004511 switch (Inst.getOpcode()) {
4512 default:
4513 llvm_unreachable("unexpected instruction opcode");
4514 case Mips::DROL:
4515 FirstShift = Mips::DSRLV;
4516 SecondShift = Mips::DSLLV;
4517 break;
4518 case Mips::DROR:
4519 FirstShift = Mips::DSLLV;
4520 SecondShift = Mips::DSRLV;
4521 break;
4522 }
4523
4524 ATReg = getATReg(Inst.getLoc());
4525 if (!ATReg)
4526 return true;
4527
Daniel Sandersa736b372016-04-29 13:33:12 +00004528 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4529 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4530 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4531 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004532
4533 return false;
4534 }
4535
4536 return true;
4537}
4538
4539bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004540 MCStreamer &Out,
4541 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004542 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004543 unsigned ATReg = Mips::NoRegister;
4544 unsigned DReg = Inst.getOperand(0).getReg();
4545 unsigned SReg = Inst.getOperand(1).getReg();
4546 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4547
4548 unsigned FirstShift = Mips::NOP;
4549 unsigned SecondShift = Mips::NOP;
4550
4551 MCInst TmpInst;
4552
4553 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004554 unsigned FinalOpcode = Mips::NOP;
4555 if (ImmValue == 0)
4556 FinalOpcode = Mips::DROTR;
4557 else if (ImmValue % 32 == 0)
4558 FinalOpcode = Mips::DROTR32;
4559 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4560 if (Inst.getOpcode() == Mips::DROLImm)
4561 FinalOpcode = Mips::DROTR32;
4562 else
4563 FinalOpcode = Mips::DROTR;
4564 } else if (ImmValue >= 33) {
4565 if (Inst.getOpcode() == Mips::DROLImm)
4566 FinalOpcode = Mips::DROTR;
4567 else
4568 FinalOpcode = Mips::DROTR32;
4569 }
4570
4571 uint64_t ShiftValue = ImmValue % 32;
4572 if (Inst.getOpcode() == Mips::DROLImm)
4573 ShiftValue = (32 - ImmValue % 32) % 32;
4574
Daniel Sandersa736b372016-04-29 13:33:12 +00004575 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004576
4577 return false;
4578 }
4579
4580 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004581 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004582 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004583 return false;
4584 }
4585
4586 switch (Inst.getOpcode()) {
4587 default:
4588 llvm_unreachable("unexpected instruction opcode");
4589 case Mips::DROLImm:
4590 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4591 FirstShift = Mips::DSLL;
4592 SecondShift = Mips::DSRL32;
4593 }
4594 if (ImmValue == 32) {
4595 FirstShift = Mips::DSLL32;
4596 SecondShift = Mips::DSRL32;
4597 }
4598 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4599 FirstShift = Mips::DSLL32;
4600 SecondShift = Mips::DSRL;
4601 }
4602 break;
4603 case Mips::DRORImm:
4604 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4605 FirstShift = Mips::DSRL;
4606 SecondShift = Mips::DSLL32;
4607 }
4608 if (ImmValue == 32) {
4609 FirstShift = Mips::DSRL32;
4610 SecondShift = Mips::DSLL32;
4611 }
4612 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4613 FirstShift = Mips::DSRL32;
4614 SecondShift = Mips::DSLL;
4615 }
4616 break;
4617 }
4618
4619 ATReg = getATReg(Inst.getLoc());
4620 if (!ATReg)
4621 return true;
4622
Daniel Sandersa736b372016-04-29 13:33:12 +00004623 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4624 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4625 Inst.getLoc(), STI);
4626 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004627
4628 return false;
4629 }
4630
4631 return true;
4632}
4633
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004634bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4635 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004636 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004637 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4638 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4639
Daniel Sandersa736b372016-04-29 13:33:12 +00004640 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004641 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004642 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004643 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004644 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4645 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004646
4647 return false;
4648}
4649
Simon Dardis3c82a642017-02-08 16:25:05 +00004650bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4651 const MCSubtargetInfo *STI) {
4652 MipsTargetStreamer &TOut = getTargetStreamer();
4653 unsigned ATReg = Mips::NoRegister;
4654 unsigned DstReg = Inst.getOperand(0).getReg();
4655 unsigned SrcReg = Inst.getOperand(1).getReg();
4656 int32_t ImmValue = Inst.getOperand(2).getImm();
4657
4658 ATReg = getATReg(IDLoc);
4659 if (!ATReg)
4660 return true;
4661
4662 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI);
4663
4664 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4665 SrcReg, ATReg, IDLoc, STI);
4666
4667 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4668
4669 return false;
4670}
4671
4672bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4673 const MCSubtargetInfo *STI) {
4674 MipsTargetStreamer &TOut = getTargetStreamer();
4675 unsigned ATReg = Mips::NoRegister;
4676 unsigned DstReg = Inst.getOperand(0).getReg();
4677 unsigned SrcReg = Inst.getOperand(1).getReg();
4678 unsigned TmpReg = Inst.getOperand(2).getReg();
4679
4680 ATReg = getATReg(Inst.getLoc());
4681 if (!ATReg)
4682 return true;
4683
4684 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4685 SrcReg, TmpReg, IDLoc, STI);
4686
4687 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4688
4689 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4690 DstReg, DstReg, 0x1F, IDLoc, STI);
4691
4692 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4693
4694 if (useTraps()) {
4695 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4696 } else {
4697 MCContext & Context = TOut.getStreamer().getContext();
4698 MCSymbol * BrTarget = Context.createTempSymbol();
4699 MCOperand LabelOp =
4700 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4701
4702 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4703 if (AssemblerOptions.back()->isReorder())
4704 TOut.emitNop(IDLoc, STI);
4705 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4706
4707 TOut.getStreamer().EmitLabel(BrTarget);
4708 }
4709 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4710
4711 return false;
4712}
4713
4714bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4715 const MCSubtargetInfo *STI) {
4716 MipsTargetStreamer &TOut = getTargetStreamer();
4717 unsigned ATReg = Mips::NoRegister;
4718 unsigned DstReg = Inst.getOperand(0).getReg();
4719 unsigned SrcReg = Inst.getOperand(1).getReg();
4720 unsigned TmpReg = Inst.getOperand(2).getReg();
4721
4722 ATReg = getATReg(IDLoc);
4723 if (!ATReg)
4724 return true;
4725
4726 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4727 SrcReg, TmpReg, IDLoc, STI);
4728
4729 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4730 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4731 if (useTraps()) {
4732 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4733 } else {
4734 MCContext & Context = TOut.getStreamer().getContext();
4735 MCSymbol * BrTarget = Context.createTempSymbol();
4736 MCOperand LabelOp =
4737 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4738
4739 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4740 if (AssemblerOptions.back()->isReorder())
4741 TOut.emitNop(IDLoc, STI);
4742 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4743
4744 TOut.getStreamer().EmitLabel(BrTarget);
4745 }
4746
4747 return false;
4748}
4749
4750bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4751 const MCSubtargetInfo *STI) {
4752 MipsTargetStreamer &TOut = getTargetStreamer();
4753 unsigned DstReg = Inst.getOperand(0).getReg();
4754 unsigned SrcReg = Inst.getOperand(1).getReg();
4755 unsigned TmpReg = Inst.getOperand(2).getReg();
4756
4757 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4758 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4759
4760 return false;
4761}
4762
Simon Dardisaff4d142016-10-18 14:28:00 +00004763// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4764// lw $<reg+1>>, offset+4($reg2)'
4765// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4766// sw $<reg+1>>, offset+4($reg2)'
4767// for O32.
4768bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4769 MCStreamer &Out,
4770 const MCSubtargetInfo *STI,
4771 bool IsLoad) {
4772 if (!isABI_O32())
4773 return true;
4774
4775 warnIfNoMacro(IDLoc);
4776
4777 MipsTargetStreamer &TOut = getTargetStreamer();
4778 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4779 unsigned FirstReg = Inst.getOperand(0).getReg();
4780 unsigned SecondReg = nextReg(FirstReg);
4781 unsigned BaseReg = Inst.getOperand(1).getReg();
4782 if (!SecondReg)
4783 return true;
4784
4785 warnIfRegIndexIsAT(FirstReg, IDLoc);
4786
4787 assert(Inst.getOperand(2).isImm() &&
4788 "Offset for load macro is not immediate!");
4789
4790 MCOperand &FirstOffset = Inst.getOperand(2);
4791 signed NextOffset = FirstOffset.getImm() + 4;
4792 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4793
4794 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4795 return true;
4796
4797 // For loads, clobber the base register with the second load instead of the
4798 // first if the BaseReg == FirstReg.
4799 if (FirstReg != BaseReg || !IsLoad) {
4800 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4801 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4802 } else {
4803 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4804 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4805 }
4806
4807 return false;
4808}
4809
Simon Dardis43115a12016-11-21 20:30:41 +00004810bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4811 const MCSubtargetInfo *STI) {
4812
4813 warnIfNoMacro(IDLoc);
4814 MipsTargetStreamer &TOut = getTargetStreamer();
4815
4816 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4817 Inst.getOperand(2).getReg() != Mips::ZERO) {
4818 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4819 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4820 IDLoc, STI);
4821 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4822 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4823 return false;
4824 }
4825
4826 unsigned Reg = 0;
4827 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4828 Reg = Inst.getOperand(2).getReg();
4829 } else {
4830 Reg = Inst.getOperand(1).getReg();
4831 }
4832 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4833 return false;
4834}
4835
4836bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4837 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004838 warnIfNoMacro(IDLoc);
4839 MipsTargetStreamer &TOut = getTargetStreamer();
4840
4841 unsigned Opc;
4842 int64_t Imm = Inst.getOperand(2).getImm();
4843 unsigned Reg = Inst.getOperand(1).getReg();
4844
4845 if (Imm == 0) {
4846 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4847 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4848 return false;
4849 } else {
4850
4851 if (Reg == Mips::ZERO) {
4852 Warning(IDLoc, "comparison is always false");
4853 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4854 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4855 return false;
4856 }
4857
4858 if (Imm > -0x8000 && Imm < 0) {
4859 Imm = -Imm;
4860 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4861 } else {
4862 Opc = Mips::XORi;
4863 }
4864 }
4865 if (!isUInt<16>(Imm)) {
4866 unsigned ATReg = getATReg(IDLoc);
4867 if (!ATReg)
4868 return true;
4869
4870 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4871 Out, STI))
4872 return true;
4873
4874 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4875 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4876 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4877 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4878 return false;
4879 }
4880
4881 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4882 Imm, IDLoc, STI);
4883 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4884 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4885 return false;
4886}
4887
Daniel Sandersc5537422016-07-27 13:49:44 +00004888unsigned
4889MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
4890 const OperandVector &Operands) {
4891 switch (Inst.getOpcode()) {
4892 default:
4893 return Match_Success;
4894 case Mips::DATI:
4895 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00004896 case Mips::DATI_MM64R6:
4897 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00004898 if (static_cast<MipsOperand &>(*Operands[1])
4899 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
4900 return Match_Success;
4901 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00004902 }
4903}
Simon Dardis730fdb72017-01-16 13:55:58 +00004904
Matheus Almeida595fcab2014-06-11 15:05:56 +00004905unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00004906 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00004907 // As described by the MIPSR6 spec, daui must not use the zero operand for
4908 // its source operand.
4909 case Mips::DAUI:
4910 case Mips::DAUI_MM64R6:
4911 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4912 Inst.getOperand(1).getReg() == Mips::ZERO_64)
4913 return Match_RequiresNoZeroRegister;
4914 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00004915 // As described by the Mips32r2 spec, the registers Rd and Rs for
4916 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00004917 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00004918 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00004919 case Mips::JALR_HB:
4920 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00004921 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00004922 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4923 return Match_RequiresDifferentSrcAndDst;
4924 return Match_Success;
4925 case Mips::LWP_MM:
4926 case Mips::LWP_MMR6:
4927 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
4928 return Match_RequiresDifferentSrcAndDst;
4929 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00004930 case Mips::SYNC:
4931 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
4932 return Match_NonZeroOperandForSync;
4933 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004934 // As described the MIPSR6 spec, the compact branches that compare registers
4935 // must:
4936 // a) Not use the zero register.
4937 // b) Not use the same register twice.
4938 // c) rs < rt for bnec, beqc.
4939 // NB: For this case, the encoding will swap the operands as their
4940 // ordering doesn't matter. GAS performs this transformation too.
4941 // Hence, that constraint does not have to be enforced.
4942 //
4943 // The compact branches that branch iff the signed addition of two registers
4944 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
4945 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004946 case Mips::BLEZC: case Mips::BLEZC_MMR6:
4947 case Mips::BGEZC: case Mips::BGEZC_MMR6:
4948 case Mips::BGTZC: case Mips::BGTZC_MMR6:
4949 case Mips::BLTZC: case Mips::BLTZC_MMR6:
4950 case Mips::BEQZC: case Mips::BEQZC_MMR6:
4951 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004952 case Mips::BLEZC64:
4953 case Mips::BGEZC64:
4954 case Mips::BGTZC64:
4955 case Mips::BLTZC64:
4956 case Mips::BEQZC64:
4957 case Mips::BNEZC64:
4958 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4959 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004960 return Match_RequiresNoZeroRegister;
4961 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004962 case Mips::BGEC: case Mips::BGEC_MMR6:
4963 case Mips::BLTC: case Mips::BLTC_MMR6:
4964 case Mips::BGEUC: case Mips::BGEUC_MMR6:
4965 case Mips::BLTUC: case Mips::BLTUC_MMR6:
4966 case Mips::BEQC: case Mips::BEQC_MMR6:
4967 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004968 case Mips::BGEC64:
4969 case Mips::BLTC64:
4970 case Mips::BGEUC64:
4971 case Mips::BLTUC64:
4972 case Mips::BEQC64:
4973 case Mips::BNEC64:
4974 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4975 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004976 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00004977 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4978 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004979 return Match_RequiresNoZeroRegister;
4980 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4981 return Match_RequiresDifferentOperands;
4982 return Match_Success;
Simon Dardis55e44672017-09-14 17:27:53 +00004983 case Mips::DINS:
4984 case Mips::DINS_MM64R6: {
4985 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
4986 "Operands must be immediates for dins!");
4987 const signed Pos = Inst.getOperand(2).getImm();
4988 const signed Size = Inst.getOperand(3).getImm();
4989 if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
4990 return Match_RequiresPosSizeRange0_32;
4991 return Match_Success;
4992 }
4993 case Mips::DINSM:
4994 case Mips::DINSM_MM64R6:
4995 case Mips::DINSU:
4996 case Mips::DINSU_MM64R6: {
4997 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
4998 "Operands must be immediates for dinsm/dinsu!");
4999 const signed Pos = Inst.getOperand(2).getImm();
5000 const signed Size = Inst.getOperand(3).getImm();
5001 if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
5002 return Match_RequiresPosSizeRange33_64;
5003 return Match_Success;
5004 }
5005 case Mips::DEXT:
5006 case Mips::DEXT_MM64R6: {
5007 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5008 "Operands must be immediates for DEXTM!");
5009 const signed Pos = Inst.getOperand(2).getImm();
5010 const signed Size = Inst.getOperand(3).getImm();
5011 if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
5012 return Match_RequiresPosSizeUImm6;
5013 return Match_Success;
5014 }
5015 case Mips::DEXTM:
5016 case Mips::DEXTU:
5017 case Mips::DEXTM_MM64R6:
5018 case Mips::DEXTU_MM64R6: {
5019 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5020 "Operands must be immediates for dextm/dextu!");
5021 const signed Pos = Inst.getOperand(2).getImm();
5022 const signed Size = Inst.getOperand(3).getImm();
5023 if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
5024 return Match_RequiresPosSizeRange33_64;
5025 return Match_Success;
5026 }
Simon Dardisb60833c2016-05-31 17:34:42 +00005027 }
Simon Dardis730fdb72017-01-16 13:55:58 +00005028
5029 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
5030 if ((TSFlags & MipsII::HasFCCRegOperand) &&
5031 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
5032 return Match_NoFCCRegisterForCurrentISA;
5033
5034 return Match_Success;
5035
Matheus Almeida595fcab2014-06-11 15:05:56 +00005036}
5037
Daniel Sanders52da7af2015-11-06 12:11:03 +00005038static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
5039 uint64_t ErrorInfo) {
5040 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
5041 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
5042 if (ErrorLoc == SMLoc())
5043 return Loc;
5044 return ErrorLoc;
5045 }
5046 return Loc;
5047}
5048
David Blaikie960ea3f2014-06-08 16:18:35 +00005049bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5050 OperandVector &Operands,
5051 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005052 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005053 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005054 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005055 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005056 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005057
5058 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005059 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005060 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005061 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005062 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005063 case Match_MissingFeature:
5064 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5065 return true;
5066 case Match_InvalidOperand: {
5067 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005068 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005069 if (ErrorInfo >= Operands.size())
5070 return Error(IDLoc, "too few operands for instruction");
5071
Daniel Sanders52da7af2015-11-06 12:11:03 +00005072 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005073 if (ErrorLoc == SMLoc())
5074 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005075 }
5076
5077 return Error(ErrorLoc, "invalid operand for instruction");
5078 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005079 case Match_NonZeroOperandForSync:
5080 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005081 case Match_MnemonicFail:
5082 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005083 case Match_RequiresDifferentSrcAndDst:
5084 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005085 case Match_RequiresDifferentOperands:
5086 return Error(IDLoc, "registers must be different");
5087 case Match_RequiresNoZeroRegister:
5088 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005089 case Match_RequiresSameSrcAndDst:
5090 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005091 case Match_NoFCCRegisterForCurrentISA:
5092 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5093 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005094 case Match_Immz:
5095 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005096 case Match_UImm1_0:
5097 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5098 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005099 case Match_UImm2_0:
5100 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5101 "expected 2-bit unsigned immediate");
5102 case Match_UImm2_1:
5103 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5104 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005105 case Match_UImm3_0:
5106 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5107 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005108 case Match_UImm4_0:
5109 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5110 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005111 case Match_SImm4_0:
5112 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5113 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005114 case Match_UImm5_0:
5115 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5116 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005117 case Match_SImm5_0:
5118 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5119 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005120 case Match_UImm5_1:
5121 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5122 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005123 case Match_UImm5_32:
5124 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5125 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005126 case Match_UImm5_33:
5127 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5128 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005129 case Match_UImm5_0_Report_UImm6:
5130 // This is used on UImm5 operands that have a corresponding UImm5_32
5131 // operand to avoid confusing the user.
5132 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5133 "expected 6-bit unsigned immediate");
5134 case Match_UImm5_Lsl2:
5135 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5136 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005137 case Match_UImmRange2_64:
5138 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5139 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005140 case Match_UImm6_0:
5141 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5142 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005143 case Match_UImm6_Lsl2:
5144 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5145 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005146 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005147 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5148 "expected 6-bit signed immediate");
5149 case Match_UImm7_0:
5150 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5151 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005152 case Match_UImm7_N1:
5153 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5154 "expected immediate in range -1 .. 126");
5155 case Match_SImm7_Lsl2:
5156 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5157 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005158 case Match_UImm8_0:
5159 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5160 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005161 case Match_UImm10_0:
5162 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5163 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005164 case Match_SImm10_0:
5165 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5166 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005167 case Match_SImm11_0:
5168 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5169 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005170 case Match_UImm16:
5171 case Match_UImm16_Relaxed:
Petar Jovanovice4dacb72017-09-12 21:43:33 +00005172 case Match_UImm16_AltRelaxed:
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005173 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5174 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005175 case Match_SImm16:
5176 case Match_SImm16_Relaxed:
5177 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5178 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005179 case Match_SImm19_Lsl2:
5180 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5181 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005182 case Match_UImm20_0:
5183 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5184 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005185 case Match_UImm26_0:
5186 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5187 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005188 case Match_SImm32:
5189 case Match_SImm32_Relaxed:
5190 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5191 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005192 case Match_UImm32_Coerced:
5193 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5194 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005195 case Match_MemSImm9:
5196 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5197 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005198 case Match_MemSImm10:
5199 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5200 "expected memory with 10-bit signed offset");
5201 case Match_MemSImm10Lsl1:
5202 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5203 "expected memory with 11-bit signed offset and multiple of 2");
5204 case Match_MemSImm10Lsl2:
5205 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5206 "expected memory with 12-bit signed offset and multiple of 4");
5207 case Match_MemSImm10Lsl3:
5208 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5209 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005210 case Match_MemSImm11:
5211 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5212 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005213 case Match_MemSImm12:
5214 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5215 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005216 case Match_MemSImm16:
5217 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5218 "expected memory with 16-bit signed offset");
Simon Dardis6f83ae32017-09-14 15:17:50 +00005219 case Match_RequiresPosSizeRange0_32: {
5220 SMLoc ErrorStart = Operands[3]->getStartLoc();
5221 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5222 return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
5223 SMRange(ErrorStart, ErrorEnd));
5224 }
Simon Dardis55e44672017-09-14 17:27:53 +00005225 case Match_RequiresPosSizeUImm6: {
5226 SMLoc ErrorStart = Operands[3]->getStartLoc();
5227 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5228 return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
5229 SMRange(ErrorStart, ErrorEnd));
5230 }
Simon Dardis6f83ae32017-09-14 15:17:50 +00005231 case Match_RequiresPosSizeRange33_64: {
5232 SMLoc ErrorStart = Operands[3]->getStartLoc();
5233 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5234 return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
5235 SMRange(ErrorStart, ErrorEnd));
5236 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005237 }
Craig Topper589ceee2015-01-03 08:16:34 +00005238
5239 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005240}
5241
Toma Tabacud9d344b2015-04-27 14:05:04 +00005242void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5243 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5244 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5245 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005246}
5247
Toma Tabacu81496c12015-05-20 08:54:45 +00005248void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5249 if (!AssemblerOptions.back()->isMacro())
5250 Warning(Loc, "macro instruction expanded into multiple instructions");
5251}
5252
Daniel Sandersef638fe2014-10-03 15:37:37 +00005253void
5254MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5255 SMRange Range, bool ShowColors) {
5256 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005257 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005258 ShowColors);
5259}
5260
Jack Carter1ac53222013-02-20 23:11:17 +00005261int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005262 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005263
Vladimir Medic4c299852013-11-06 11:27:05 +00005264 CC = StringSwitch<unsigned>(Name)
5265 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005266 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005267 .Case("a0", 4)
5268 .Case("a1", 5)
5269 .Case("a2", 6)
5270 .Case("a3", 7)
5271 .Case("v0", 2)
5272 .Case("v1", 3)
5273 .Case("s0", 16)
5274 .Case("s1", 17)
5275 .Case("s2", 18)
5276 .Case("s3", 19)
5277 .Case("s4", 20)
5278 .Case("s5", 21)
5279 .Case("s6", 22)
5280 .Case("s7", 23)
5281 .Case("k0", 26)
5282 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005283 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005284 .Case("sp", 29)
5285 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005286 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005287 .Case("ra", 31)
5288 .Case("t0", 8)
5289 .Case("t1", 9)
5290 .Case("t2", 10)
5291 .Case("t3", 11)
5292 .Case("t4", 12)
5293 .Case("t5", 13)
5294 .Case("t6", 14)
5295 .Case("t7", 15)
5296 .Case("t8", 24)
5297 .Case("t9", 25)
5298 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005299
Toma Tabacufda445c2014-09-15 15:33:01 +00005300 if (!(isABI_N32() || isABI_N64()))
5301 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005302
Daniel Sandersef638fe2014-10-03 15:37:37 +00005303 if (12 <= CC && CC <= 15) {
5304 // Name is one of t4-t7
5305 AsmToken RegTok = getLexer().peekTok();
5306 SMRange RegRange = RegTok.getLocRange();
5307
5308 StringRef FixedName = StringSwitch<StringRef>(Name)
5309 .Case("t4", "t0")
5310 .Case("t5", "t1")
5311 .Case("t6", "t2")
5312 .Case("t7", "t3")
5313 .Default("");
5314 assert(FixedName != "" && "Register name is not one of t4-t7.");
5315
5316 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5317 "Did you mean $" + FixedName + "?", RegRange);
5318 }
5319
Toma Tabacufda445c2014-09-15 15:33:01 +00005320 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5321 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5322 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5323 if (8 <= CC && CC <= 11)
5324 CC += 4;
5325
5326 if (CC == -1)
5327 CC = StringSwitch<unsigned>(Name)
5328 .Case("a4", 8)
5329 .Case("a5", 9)
5330 .Case("a6", 10)
5331 .Case("a7", 11)
5332 .Case("kt0", 26)
5333 .Case("kt1", 27)
5334 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005335
5336 return CC;
5337}
Jack Carterd0bd6422013-04-18 00:41:53 +00005338
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005339int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5340 int CC;
5341
5342 CC = StringSwitch<unsigned>(Name)
5343 .Case("hwr_cpunum", 0)
5344 .Case("hwr_synci_step", 1)
5345 .Case("hwr_cc", 2)
5346 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005347 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005348 .Default(-1);
5349
5350 return CC;
5351}
5352
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005353int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005354 if (Name[0] == 'f') {
5355 StringRef NumString = Name.substr(1);
5356 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005357 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005358 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005359 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005360 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005361 return IntVal;
5362 }
5363 return -1;
5364}
Jack Cartera63b16a2012-09-07 00:23:42 +00005365
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005366int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005367 if (Name.startswith("fcc")) {
5368 StringRef NumString = Name.substr(3);
5369 unsigned IntVal;
5370 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005371 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005372 if (IntVal > 7) // There are only 8 fcc registers.
5373 return -1;
5374 return IntVal;
5375 }
5376 return -1;
5377}
5378
5379int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005380 if (Name.startswith("ac")) {
5381 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005382 unsigned IntVal;
5383 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005384 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005385 if (IntVal > 3) // There are only 3 acc registers.
5386 return -1;
5387 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005388 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005389 return -1;
5390}
Jack Carterd0bd6422013-04-18 00:41:53 +00005391
Jack Carter5dc8ac92013-09-25 23:50:44 +00005392int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5393 unsigned IntVal;
5394
5395 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5396 return -1;
5397
5398 if (IntVal > 31)
5399 return -1;
5400
5401 return IntVal;
5402}
5403
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005404int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5405 int CC;
5406
5407 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005408 .Case("msair", 0)
5409 .Case("msacsr", 1)
5410 .Case("msaaccess", 2)
5411 .Case("msasave", 3)
5412 .Case("msamodify", 4)
5413 .Case("msarequest", 5)
5414 .Case("msamap", 6)
5415 .Case("msaunmap", 7)
5416 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005417
5418 return CC;
5419}
5420
Simon Dardis3aa8a902017-02-06 12:43:46 +00005421bool MipsAsmParser::canUseATReg() {
5422 return AssemblerOptions.back()->getATRegIndex() != 0;
5423}
5424
Toma Tabacu89a712b2015-04-15 10:48:56 +00005425unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005426 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005427 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005428 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005429 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005430 return 0;
5431 }
5432 unsigned AT = getReg(
5433 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005434 return AT;
5435}
Jack Carter0b744b32012-10-04 02:29:46 +00005436
Jack Carterd0bd6422013-04-18 00:41:53 +00005437unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005438 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005439}
5440
Toma Tabacu13964452014-09-04 13:23:44 +00005441bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005442 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005443 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005444
Jack Carter30a59822012-10-04 04:03:53 +00005445 // Check if the current operand has a custom associated parser, if so, try to
5446 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005447 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5448 if (ResTy == MatchOperand_Success)
5449 return false;
5450 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5451 // there was a match, but an error occurred, in which case, just return that
5452 // the operand parsing failed.
5453 if (ResTy == MatchOperand_ParseFail)
5454 return true;
5455
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005456 DEBUG(dbgs() << ".. Generic Parser\n");
5457
Jack Carterb4dbc172012-09-05 23:34:03 +00005458 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005459 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005460 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005461 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005462
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005463 // Almost all registers have been parsed by custom parsers. There is only
5464 // one exception to this. $zero (and it's alias $0) will reach this point
5465 // for div, divu, and similar instructions because it is not an operand
5466 // to the instruction definition but an explicit register. Special case
5467 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005468 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005469 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005470
Jack Carterd0bd6422013-04-18 00:41:53 +00005471 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005472 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005473 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005474 return true;
5475
Jack Carter873c7242013-01-12 01:03:14 +00005476 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005477 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005478 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005479 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005480 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005481
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005482 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005483 return false;
5484 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005485 default: {
5486 DEBUG(dbgs() << ".. generic integer expression\n");
5487
5488 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005489 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005490 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005491 return true;
5492
Jack Carter873c7242013-01-12 01:03:14 +00005493 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5494
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005495 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005496 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005497 }
Jack Carter0b744b32012-10-04 02:29:46 +00005498 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005499 return true;
5500}
5501
Jack Carterb5cf5902013-04-17 00:18:04 +00005502bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005503 switch (Expr->getKind()) {
5504 case MCExpr::Constant:
5505 return true;
5506 case MCExpr::SymbolRef:
5507 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
Simon Dardisc6be2252017-08-09 10:47:52 +00005508 case MCExpr::Binary: {
Simon Dardis02c9a3d2017-08-18 13:27:02 +00005509 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
Simon Dardisc6be2252017-08-09 10:47:52 +00005510 if (!isEvaluated(BE->getLHS()))
5511 return false;
5512 return isEvaluated(BE->getRHS());
5513 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005514 case MCExpr::Unary:
5515 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005516 case MCExpr::Target:
5517 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005518 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005519 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005520}
Jack Carterd0bd6422013-04-18 00:41:53 +00005521
Jack Carterb4dbc172012-09-05 23:34:03 +00005522bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5523 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005524 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005525 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005526 if (ResTy == MatchOperand_Success) {
5527 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005528 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005529 StartLoc = Operand.getStartLoc();
5530 EndLoc = Operand.getEndLoc();
5531
5532 // AFAIK, we only support numeric registers and named GPR's in CFI
5533 // directives.
5534 // Don't worry about eating tokens before failing. Using an unrecognised
5535 // register is a parse error.
5536 if (Operand.isGPRAsmReg()) {
5537 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005538 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005539 }
5540
5541 return (RegNo == (unsigned)-1);
5542 }
5543
5544 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005545 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005546}
5547
Jack Carterb5cf5902013-04-17 00:18:04 +00005548bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005549 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005550
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005551 if (isParenExpr)
5552 return getParser().parseParenExprOfDepth(0, Res, S);
5553 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005554}
5555
Alex Bradbury58eba092016-11-01 16:32:05 +00005556OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005557MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005558 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005559 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005560 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005561 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005562 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005563 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005564 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005565 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005566
Jack Carterb5cf5902013-04-17 00:18:04 +00005567 if (getLexer().getKind() == AsmToken::LParen) {
5568 Parser.Lex();
5569 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005570 }
5571
Jack Carterb5cf5902013-04-17 00:18:04 +00005572 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005573 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005574 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005575
Jack Carterd0bd6422013-04-18 00:41:53 +00005576 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005577 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005578 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005579 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005580 SMLoc E =
5581 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005582 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005583 return MatchOperand_Success;
5584 }
5585 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005586 SMLoc E =
5587 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005588
Jack Carterd0bd6422013-04-18 00:41:53 +00005589 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005590 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005591 auto Base = MipsOperand::createGPRReg(
5592 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005593 Operands.push_back(
5594 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005595 return MatchOperand_Success;
5596 }
Simon Dardis858915f2016-10-18 15:17:17 +00005597 MCBinaryExpr::Opcode Opcode;
5598 // GAS and LLVM treat comparison operators different. GAS will generate -1
5599 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5600 // highly unlikely to be found in a memory offset expression, we don't
5601 // handle them.
5602 switch (Tok.getKind()) {
5603 case AsmToken::Plus:
5604 Opcode = MCBinaryExpr::Add;
5605 Parser.Lex();
5606 break;
5607 case AsmToken::Minus:
5608 Opcode = MCBinaryExpr::Sub;
5609 Parser.Lex();
5610 break;
5611 case AsmToken::Star:
5612 Opcode = MCBinaryExpr::Mul;
5613 Parser.Lex();
5614 break;
5615 case AsmToken::Pipe:
5616 Opcode = MCBinaryExpr::Or;
5617 Parser.Lex();
5618 break;
5619 case AsmToken::Amp:
5620 Opcode = MCBinaryExpr::And;
5621 Parser.Lex();
5622 break;
5623 case AsmToken::LessLess:
5624 Opcode = MCBinaryExpr::Shl;
5625 Parser.Lex();
5626 break;
5627 case AsmToken::GreaterGreater:
5628 Opcode = MCBinaryExpr::LShr;
5629 Parser.Lex();
5630 break;
5631 case AsmToken::Caret:
5632 Opcode = MCBinaryExpr::Xor;
5633 Parser.Lex();
5634 break;
5635 case AsmToken::Slash:
5636 Opcode = MCBinaryExpr::Div;
5637 Parser.Lex();
5638 break;
5639 case AsmToken::Percent:
5640 Opcode = MCBinaryExpr::Mod;
5641 Parser.Lex();
5642 break;
5643 default:
5644 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5645 return MatchOperand_ParseFail;
5646 }
5647 const MCExpr * NextExpr;
5648 if (getParser().parseExpression(NextExpr))
5649 return MatchOperand_ParseFail;
5650 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005651 }
5652
Jack Carterd0bd6422013-04-18 00:41:53 +00005653 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005654 }
5655
Toma Tabacu13964452014-09-04 13:23:44 +00005656 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005657 if (Res != MatchOperand_Success)
5658 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005659
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005660 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005661 Error(Parser.getTok().getLoc(), "')' expected");
5662 return MatchOperand_ParseFail;
5663 }
5664
Jack Carter873c7242013-01-12 01:03:14 +00005665 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5666
Jack Carterd0bd6422013-04-18 00:41:53 +00005667 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005668
Craig Topper062a2ba2014-04-25 05:30:21 +00005669 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005670 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005671
Jack Carterd0bd6422013-04-18 00:41:53 +00005672 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005673 std::unique_ptr<MipsOperand> op(
5674 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005675 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005676 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005677 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005678 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005679 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5680 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005681 if (IdVal->evaluateAsAbsolute(Imm))
5682 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005683 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005684 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005685 getContext());
5686 }
5687
David Blaikie960ea3f2014-06-08 16:18:35 +00005688 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005689 return MatchOperand_Success;
5690}
5691
David Blaikie960ea3f2014-06-08 16:18:35 +00005692bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005693 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005694 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00005695 if (Sym) {
5696 SMLoc S = Parser.getTok().getLoc();
5697 const MCExpr *Expr;
5698 if (Sym->isVariable())
5699 Expr = Sym->getVariableValue();
5700 else
5701 return false;
5702 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005703 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005704 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005705 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005706 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005707 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005708 if (ResTy == MatchOperand_Success) {
5709 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005710 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00005711 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005712 llvm_unreachable("Should never ParseFail");
5713 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00005714 }
Jack Carterd76b2372013-03-21 21:44:16 +00005715 }
5716 }
5717 return false;
5718}
Jack Carterd0bd6422013-04-18 00:41:53 +00005719
Alex Bradbury58eba092016-11-01 16:32:05 +00005720OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005721MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00005722 StringRef Identifier,
5723 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005724 int Index = matchCPURegisterName(Identifier);
5725 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005726 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005727 Index, Identifier, getContext().getRegisterInfo(), S,
5728 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005729 return MatchOperand_Success;
5730 }
5731
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005732 Index = matchHWRegsRegisterName(Identifier);
5733 if (Index != -1) {
5734 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005735 Index, Identifier, getContext().getRegisterInfo(), S,
5736 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005737 return MatchOperand_Success;
5738 }
5739
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005740 Index = matchFPURegisterName(Identifier);
5741 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005742 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005743 Index, Identifier, getContext().getRegisterInfo(), S,
5744 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005745 return MatchOperand_Success;
5746 }
5747
5748 Index = matchFCCRegisterName(Identifier);
5749 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005750 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005751 Index, Identifier, getContext().getRegisterInfo(), S,
5752 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005753 return MatchOperand_Success;
5754 }
5755
5756 Index = matchACRegisterName(Identifier);
5757 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005758 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005759 Index, Identifier, getContext().getRegisterInfo(), S,
5760 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005761 return MatchOperand_Success;
5762 }
5763
5764 Index = matchMSA128RegisterName(Identifier);
5765 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005766 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005767 Index, Identifier, getContext().getRegisterInfo(), S,
5768 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005769 return MatchOperand_Success;
5770 }
5771
5772 Index = matchMSA128CtrlRegisterName(Identifier);
5773 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005774 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005775 Index, Identifier, getContext().getRegisterInfo(), S,
5776 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005777 return MatchOperand_Success;
5778 }
5779
5780 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00005781}
5782
Alex Bradbury58eba092016-11-01 16:32:05 +00005783OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005784MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005785 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00005786 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005787
5788 if (Token.is(AsmToken::Identifier)) {
5789 DEBUG(dbgs() << ".. identifier\n");
5790 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00005791 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005792 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00005793 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005794 } else if (Token.is(AsmToken::Integer)) {
5795 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00005796 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005797 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
5798 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005799 return MatchOperand_Success;
5800 }
5801
5802 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
5803
5804 return MatchOperand_NoMatch;
5805}
5806
Alex Bradbury58eba092016-11-01 16:32:05 +00005807OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005808MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005809 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005810 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005811
5812 auto Token = Parser.getTok();
5813
5814 SMLoc S = Token.getLoc();
5815
5816 if (Token.isNot(AsmToken::Dollar)) {
5817 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
5818 if (Token.is(AsmToken::Identifier)) {
5819 if (searchSymbolAlias(Operands))
5820 return MatchOperand_Success;
5821 }
5822 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
5823 return MatchOperand_NoMatch;
5824 }
5825 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005826
Toma Tabacu13964452014-09-04 13:23:44 +00005827 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00005828 if (ResTy == MatchOperand_Success) {
5829 Parser.Lex(); // $
5830 Parser.Lex(); // identifier
5831 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005832 return ResTy;
5833}
5834
Alex Bradbury58eba092016-11-01 16:32:05 +00005835OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005836MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005837 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005838 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005839
5840 SMLoc S = getLexer().getLoc();
5841
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005842 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005843 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005844 if (ResTy != MatchOperand_NoMatch)
5845 return ResTy;
5846
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005847 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00005848 const MCExpr *Expr = nullptr;
5849 if (Parser.parseExpression(Expr)) {
5850 // We have no way of knowing if a symbol was consumed so we must ParseFail
5851 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005852 }
Daniel Sandersffd84362014-04-01 10:41:48 +00005853 Operands.push_back(
5854 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005855 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00005856}
5857
Alex Bradbury58eba092016-11-01 16:32:05 +00005858OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005859MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005860 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00005861 const MCExpr *IdVal;
Simon Dardisa17a7b62017-10-10 13:34:45 +00005862 // If the first token is '$' we may have register operand. We have to reject
5863 // cases where it is not a register. Complicating the matter is that
5864 // register names are not reserved across all ABIs.
5865 // Peek past the dollar to see if it's a register name for this ABI.
Vladimir Medic2b953d02013-10-01 09:48:56 +00005866 SMLoc S = Parser.getTok().getLoc();
Simon Dardisa17a7b62017-10-10 13:34:45 +00005867 if (Parser.getTok().is(AsmToken::Dollar)) {
5868 return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
5869 ? MatchOperand_ParseFail
5870 : MatchOperand_NoMatch;
5871 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00005872 if (getParser().parseExpression(IdVal))
5873 return MatchOperand_ParseFail;
5874 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Simon Dardisa17a7b62017-10-10 13:34:45 +00005875 if (!MCE)
5876 return MatchOperand_NoMatch;
Vladimir Medic2b953d02013-10-01 09:48:56 +00005877 int64_t Val = MCE->getValue();
5878 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5879 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00005880 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00005881 return MatchOperand_Success;
5882}
5883
Alex Bradbury58eba092016-11-01 16:32:05 +00005884OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005885MipsAsmParser::parseRegisterList(OperandVector &Operands) {
5886 MCAsmParser &Parser = getParser();
5887 SmallVector<unsigned, 10> Regs;
5888 unsigned RegNo;
5889 unsigned PrevReg = Mips::NoRegister;
5890 bool RegRange = false;
5891 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5892
5893 if (Parser.getTok().isNot(AsmToken::Dollar))
5894 return MatchOperand_ParseFail;
5895
5896 SMLoc S = Parser.getTok().getLoc();
5897 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
5898 SMLoc E = getLexer().getLoc();
5899 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
5900 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
5901 if (RegRange) {
5902 // Remove last register operand because registers from register range
5903 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005904 if ((isGP64bit() && RegNo == Mips::RA_64) ||
5905 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005906 Regs.push_back(RegNo);
5907 } else {
5908 unsigned TmpReg = PrevReg + 1;
5909 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005910 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
5911 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
5912 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005913 Error(E, "invalid register operand");
5914 return MatchOperand_ParseFail;
5915 }
5916
5917 PrevReg = TmpReg;
5918 Regs.push_back(TmpReg++);
5919 }
5920 }
5921
5922 RegRange = false;
5923 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005924 if ((PrevReg == Mips::NoRegister) &&
5925 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
5926 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005927 Error(E, "$16 or $31 expected");
5928 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005929 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
5930 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
5931 !isGP64bit()) ||
5932 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
5933 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
5934 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005935 Error(E, "invalid register operand");
5936 return MatchOperand_ParseFail;
5937 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005938 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
5939 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
5940 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005941 Error(E, "consecutive register numbers expected");
5942 return MatchOperand_ParseFail;
5943 }
5944
5945 Regs.push_back(RegNo);
5946 }
5947
5948 if (Parser.getTok().is(AsmToken::Minus))
5949 RegRange = true;
5950
5951 if (!Parser.getTok().isNot(AsmToken::Minus) &&
5952 !Parser.getTok().isNot(AsmToken::Comma)) {
5953 Error(E, "',' or '-' expected");
5954 return MatchOperand_ParseFail;
5955 }
5956
5957 Lex(); // Consume comma or minus
5958 if (Parser.getTok().isNot(AsmToken::Dollar))
5959 break;
5960
5961 PrevReg = RegNo;
5962 }
5963
5964 SMLoc E = Parser.getTok().getLoc();
5965 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5966 parseMemOperand(Operands);
5967 return MatchOperand_Success;
5968}
5969
Alex Bradbury58eba092016-11-01 16:32:05 +00005970OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005971MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
5972 MCAsmParser &Parser = getParser();
5973
5974 SMLoc S = Parser.getTok().getLoc();
5975 if (parseAnyRegister(Operands) != MatchOperand_Success)
5976 return MatchOperand_ParseFail;
5977
5978 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00005979 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00005980
Benjamin Kramer2b68d152016-05-09 10:31:17 +00005981 Operands.pop_back();
5982 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005983 return MatchOperand_Success;
5984}
5985
Alex Bradbury58eba092016-11-01 16:32:05 +00005986OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00005987MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
5988 MCAsmParser &Parser = getParser();
5989 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5990 SmallVector<unsigned, 10> Regs;
5991
5992 if (Parser.getTok().isNot(AsmToken::Dollar))
5993 return MatchOperand_ParseFail;
5994
5995 SMLoc S = Parser.getTok().getLoc();
5996
5997 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5998 return MatchOperand_ParseFail;
5999
6000 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6001 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6002 Regs.push_back(RegNo);
6003
6004 SMLoc E = Parser.getTok().getLoc();
6005 if (Parser.getTok().isNot(AsmToken::Comma)) {
6006 Error(E, "',' expected");
6007 return MatchOperand_ParseFail;
6008 }
6009
6010 // Remove comma.
6011 Parser.Lex();
6012
6013 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6014 return MatchOperand_ParseFail;
6015
6016 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6017 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6018 Regs.push_back(RegNo);
6019
6020 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6021
6022 return MatchOperand_Success;
6023}
6024
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006025/// Sometimes (i.e. load/stores) the operand may be followed immediately by
6026/// either this.
6027/// ::= '(', register, ')'
6028/// handle it before we iterate so we don't get tripped up by the lack of
6029/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006030bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006031 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006032 if (getLexer().is(AsmToken::LParen)) {
6033 Operands.push_back(
6034 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
6035 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006036 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006037 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006038 return Error(Loc, "unexpected token in argument list");
6039 }
6040 if (Parser.getTok().isNot(AsmToken::RParen)) {
6041 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006042 return Error(Loc, "unexpected token, expected ')'");
6043 }
6044 Operands.push_back(
6045 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
6046 Parser.Lex();
6047 }
6048 return false;
6049}
6050
6051/// Sometimes (i.e. in MSA) the operand may be followed immediately by
6052/// either one of these.
6053/// ::= '[', register, ']'
6054/// ::= '[', integer, ']'
6055/// handle it before we iterate so we don't get tripped up by the lack of
6056/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006057bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00006058 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006059 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006060 if (getLexer().is(AsmToken::LBrac)) {
6061 Operands.push_back(
6062 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
6063 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006064 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006065 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006066 return Error(Loc, "unexpected token in argument list");
6067 }
6068 if (Parser.getTok().isNot(AsmToken::RBrac)) {
6069 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006070 return Error(Loc, "unexpected token, expected ']'");
6071 }
6072 Operands.push_back(
6073 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
6074 Parser.Lex();
6075 }
6076 return false;
6077}
6078
David Blaikie960ea3f2014-06-08 16:18:35 +00006079bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6080 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006081 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006082 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006083
6084 // We have reached first instruction, module directive are now forbidden.
6085 getTargetStreamer().forbidModuleDirective();
6086
Vladimir Medic74593e62013-07-17 15:00:42 +00006087 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006088 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006089 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00006090 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006091 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006092 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006093
6094 // Read the remaining operands.
6095 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6096 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006097 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006098 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006099 return Error(Loc, "unexpected token in argument list");
6100 }
Toma Tabacu13964452014-09-04 13:23:44 +00006101 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006102 return true;
6103 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006104
Jack Carterd0bd6422013-04-18 00:41:53 +00006105 while (getLexer().is(AsmToken::Comma)) {
6106 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006107 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006108 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006109 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006110 return Error(Loc, "unexpected token in argument list");
6111 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006112 // Parse bracket and parenthesis suffixes before we iterate
6113 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006114 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006115 return true;
6116 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006117 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006118 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006119 }
6120 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006121 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6122 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006123 return Error(Loc, "unexpected token in argument list");
6124 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006125 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006126 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006127}
6128
Nirav Dave996fc132016-05-05 14:15:46 +00006129// FIXME: Given that these have the same name, these should both be
6130// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006131bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006132 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006133 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006134}
6135
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006136bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006137 return Error(Loc, ErrorMsg);
6138}
6139
Jack Carter0b744b32012-10-04 02:29:46 +00006140bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006141 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006142 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006143
6144 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006145 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006146
6147 Parser.Lex(); // Eat "noat".
6148
Jack Carterd0bd6422013-04-18 00:41:53 +00006149 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006150 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006151 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006152 return false;
6153 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006154
6155 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006156 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006157 return false;
6158}
Jack Carterd0bd6422013-04-18 00:41:53 +00006159
Jack Carter0b744b32012-10-04 02:29:46 +00006160bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006161 // Line can be: ".set at", which sets $at to $1
6162 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006163 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006164 Parser.Lex(); // Eat "at".
6165
Jack Carter0b744b32012-10-04 02:29:46 +00006166 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006167 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006168 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006169
6170 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006171 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006172 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006173 }
6174
6175 if (getLexer().isNot(AsmToken::Equal)) {
6176 reportParseError("unexpected token, expected equals sign");
6177 return false;
6178 }
6179 Parser.Lex(); // Eat "=".
6180
6181 if (getLexer().isNot(AsmToken::Dollar)) {
6182 if (getLexer().is(AsmToken::EndOfStatement)) {
6183 reportParseError("no register specified");
6184 return false;
6185 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006186 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006187 return false;
6188 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006189 }
6190 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006191
Toma Tabacu16a74492015-02-13 10:30:57 +00006192 // Find out what "reg" is.
6193 unsigned AtRegNo;
6194 const AsmToken &Reg = Parser.getTok();
6195 if (Reg.is(AsmToken::Identifier)) {
6196 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6197 } else if (Reg.is(AsmToken::Integer)) {
6198 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006199 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006200 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006201 return false;
6202 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006203
6204 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006205 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006206 reportParseError("invalid register");
6207 return false;
6208 }
6209 Parser.Lex(); // Eat "reg".
6210
6211 // If this is not the end of the statement, report an error.
6212 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6213 reportParseError("unexpected token, expected end of statement");
6214 return false;
6215 }
6216
6217 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6218
6219 Parser.Lex(); // Consume the EndOfStatement.
6220 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006221}
6222
6223bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006224 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006225 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006226 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006227 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006228 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006229 return false;
6230 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006231 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006232 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006233 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006234 return false;
6235}
6236
6237bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006238 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006239 Parser.Lex();
6240 // If this is not the end of the statement, report an error.
6241 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006242 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006243 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006244 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006245 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006246 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006247 Parser.Lex(); // Consume the EndOfStatement.
6248 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006249}
6250
6251bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006252 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006253 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006254 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006255 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006256 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006257 return false;
6258 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006259 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006260 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006261 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006262 return false;
6263}
6264
6265bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006266 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006267 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006268 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006269 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006270 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006271 return false;
6272 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006273 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006274 reportParseError("`noreorder' must be set before `nomacro'");
6275 return false;
6276 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006277 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006278 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006279 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006280 return false;
6281}
Jack Carterd76b2372013-03-21 21:44:16 +00006282
Daniel Sanders44934432014-08-07 12:03:36 +00006283bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006284 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006285 Parser.Lex();
6286
6287 // If this is not the end of the statement, report an error.
6288 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006289 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006290
6291 setFeatureBits(Mips::FeatureMSA, "msa");
6292 getTargetStreamer().emitDirectiveSetMsa();
6293 return false;
6294}
6295
6296bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006297 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006298 Parser.Lex();
6299
6300 // If this is not the end of the statement, report an error.
6301 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006302 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006303
6304 clearFeatureBits(Mips::FeatureMSA, "msa");
6305 getTargetStreamer().emitDirectiveSetNoMsa();
6306 return false;
6307}
6308
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006309bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006310 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006311 Parser.Lex(); // Eat "nodsp".
6312
6313 // If this is not the end of the statement, report an error.
6314 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6315 reportParseError("unexpected token, expected end of statement");
6316 return false;
6317 }
6318
6319 clearFeatureBits(Mips::FeatureDSP, "dsp");
6320 getTargetStreamer().emitDirectiveSetNoDsp();
6321 return false;
6322}
6323
Toma Tabacucc2502d2014-11-04 17:18:07 +00006324bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006325 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006326 Parser.Lex(); // Eat "mips16".
6327
Jack Carter39536722014-01-22 23:08:42 +00006328 // If this is not the end of the statement, report an error.
6329 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006330 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006331 return false;
6332 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006333
6334 setFeatureBits(Mips::FeatureMips16, "mips16");
6335 getTargetStreamer().emitDirectiveSetMips16();
6336 Parser.Lex(); // Consume the EndOfStatement.
6337 return false;
6338}
6339
6340bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006341 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006342 Parser.Lex(); // Eat "nomips16".
6343
6344 // If this is not the end of the statement, report an error.
6345 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6346 reportParseError("unexpected token, expected end of statement");
6347 return false;
6348 }
6349
6350 clearFeatureBits(Mips::FeatureMips16, "mips16");
6351 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006352 Parser.Lex(); // Consume the EndOfStatement.
6353 return false;
6354}
6355
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006356bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006357 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006358 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006359 // Line can be: .set fp=32
6360 // .set fp=xx
6361 // .set fp=64
6362 Parser.Lex(); // Eat fp token
6363 AsmToken Tok = Parser.getTok();
6364 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006365 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006366 return false;
6367 }
6368 Parser.Lex(); // Eat '=' token.
6369 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006370
6371 if (!parseFpABIValue(FpAbiVal, ".set"))
6372 return false;
6373
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006374 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006375 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006376 return false;
6377 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006378 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006379 Parser.Lex(); // Consume the EndOfStatement.
6380 return false;
6381}
6382
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006383bool MipsAsmParser::parseSetOddSPRegDirective() {
6384 MCAsmParser &Parser = getParser();
6385
6386 Parser.Lex(); // Eat "oddspreg".
6387 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6388 reportParseError("unexpected token, expected end of statement");
6389 return false;
6390 }
6391
6392 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6393 getTargetStreamer().emitDirectiveSetOddSPReg();
6394 return false;
6395}
6396
6397bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6398 MCAsmParser &Parser = getParser();
6399
6400 Parser.Lex(); // Eat "nooddspreg".
6401 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6402 reportParseError("unexpected token, expected end of statement");
6403 return false;
6404 }
6405
6406 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6407 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6408 return false;
6409}
6410
Simon Dardis805f1e02017-07-11 21:28:36 +00006411bool MipsAsmParser::parseSetMtDirective() {
6412 MCAsmParser &Parser = getParser();
6413 Parser.Lex(); // Eat "mt".
6414
6415 // If this is not the end of the statement, report an error.
6416 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6417 reportParseError("unexpected token, expected end of statement");
6418 return false;
6419 }
6420
6421 setFeatureBits(Mips::FeatureMT, "mt");
6422 getTargetStreamer().emitDirectiveSetMt();
6423 Parser.Lex(); // Consume the EndOfStatement.
6424 return false;
6425}
6426
6427bool MipsAsmParser::parseSetNoMtDirective() {
6428 MCAsmParser &Parser = getParser();
6429 Parser.Lex(); // Eat "nomt".
6430
6431 // If this is not the end of the statement, report an error.
6432 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6433 reportParseError("unexpected token, expected end of statement");
6434 return false;
6435 }
6436
6437 clearFeatureBits(Mips::FeatureMT, "mt");
6438
6439 getTargetStreamer().emitDirectiveSetNoMt();
6440 Parser.Lex(); // Consume the EndOfStatement.
6441 return false;
6442}
6443
Toma Tabacu9db22db2014-09-09 10:15:38 +00006444bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006445 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006446 SMLoc Loc = getLexer().getLoc();
6447
6448 Parser.Lex();
6449 if (getLexer().isNot(AsmToken::EndOfStatement))
6450 return reportParseError("unexpected token, expected end of statement");
6451
6452 // Always keep an element on the options "stack" to prevent the user
6453 // from changing the initial options. This is how we remember them.
6454 if (AssemblerOptions.size() == 2)
6455 return reportParseError(Loc, ".set pop with no .set push");
6456
Akira Hatanakab11ef082015-11-14 06:35:56 +00006457 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006458 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006459 setAvailableFeatures(
6460 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6461 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006462
6463 getTargetStreamer().emitDirectiveSetPop();
6464 return false;
6465}
6466
6467bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006468 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006469 Parser.Lex();
6470 if (getLexer().isNot(AsmToken::EndOfStatement))
6471 return reportParseError("unexpected token, expected end of statement");
6472
6473 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006474 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006475 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006476
6477 getTargetStreamer().emitDirectiveSetPush();
6478 return false;
6479}
6480
Toma Tabacu29696502015-06-02 09:48:04 +00006481bool MipsAsmParser::parseSetSoftFloatDirective() {
6482 MCAsmParser &Parser = getParser();
6483 Parser.Lex();
6484 if (getLexer().isNot(AsmToken::EndOfStatement))
6485 return reportParseError("unexpected token, expected end of statement");
6486
6487 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6488 getTargetStreamer().emitDirectiveSetSoftFloat();
6489 return false;
6490}
6491
6492bool MipsAsmParser::parseSetHardFloatDirective() {
6493 MCAsmParser &Parser = getParser();
6494 Parser.Lex();
6495 if (getLexer().isNot(AsmToken::EndOfStatement))
6496 return reportParseError("unexpected token, expected end of statement");
6497
6498 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6499 getTargetStreamer().emitDirectiveSetHardFloat();
6500 return false;
6501}
6502
Jack Carterd76b2372013-03-21 21:44:16 +00006503bool MipsAsmParser::parseSetAssignment() {
6504 StringRef Name;
6505 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006506 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006507
6508 if (Parser.parseIdentifier(Name))
6509 reportParseError("expected identifier after .set");
6510
6511 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006512 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006513 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006514
Jack Carter3b2c96e2014-01-22 23:31:38 +00006515 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00006516 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00006517
Jim Grosbach6f482002015-05-18 18:43:14 +00006518 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00006519 Sym->setVariableValue(Value);
6520
6521 return false;
6522}
Jack Carterd0bd6422013-04-18 00:41:53 +00006523
Toma Tabacu26647792014-09-09 12:52:14 +00006524bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006525 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006526 Parser.Lex();
6527 if (getLexer().isNot(AsmToken::EndOfStatement))
6528 return reportParseError("unexpected token, expected end of statement");
6529
6530 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006531 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006532 setAvailableFeatures(
6533 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6534 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006535 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6536
6537 getTargetStreamer().emitDirectiveSetMips0();
6538 return false;
6539}
6540
Toma Tabacu85618b32014-08-19 14:22:52 +00006541bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006542 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006543 Parser.Lex();
6544 if (getLexer().isNot(AsmToken::Equal))
6545 return reportParseError("unexpected token, expected equals sign");
6546
6547 Parser.Lex();
6548 StringRef Arch;
6549 if (Parser.parseIdentifier(Arch))
6550 return reportParseError("expected arch identifier");
6551
6552 StringRef ArchFeatureName =
6553 StringSwitch<StringRef>(Arch)
6554 .Case("mips1", "mips1")
6555 .Case("mips2", "mips2")
6556 .Case("mips3", "mips3")
6557 .Case("mips4", "mips4")
6558 .Case("mips5", "mips5")
6559 .Case("mips32", "mips32")
6560 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006561 .Case("mips32r3", "mips32r3")
6562 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006563 .Case("mips32r6", "mips32r6")
6564 .Case("mips64", "mips64")
6565 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006566 .Case("mips64r3", "mips64r3")
6567 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006568 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006569 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006570 .Case("r4000", "mips3") // This is an implementation of Mips3.
6571 .Default("");
6572
6573 if (ArchFeatureName.empty())
6574 return reportParseError("unsupported architecture");
6575
6576 selectArch(ArchFeatureName);
6577 getTargetStreamer().emitDirectiveSetArch(Arch);
6578 return false;
6579}
6580
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006581bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006582 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006583 Parser.Lex();
6584 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006585 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006586
Matheus Almeida2852af82014-04-22 10:15:54 +00006587 switch (Feature) {
6588 default:
6589 llvm_unreachable("Unimplemented feature");
6590 case Mips::FeatureDSP:
6591 setFeatureBits(Mips::FeatureDSP, "dsp");
6592 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006593 break;
Petar Jovanovic65f10242017-10-05 17:40:32 +00006594 case Mips::FeatureDSPR2:
6595 setFeatureBits(Mips::FeatureDSPR2, "dspr2");
6596 getTargetStreamer().emitDirectiveSetDspr2();
6597 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006598 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006599 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006600 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006601 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006602 case Mips::FeatureMips1:
6603 selectArch("mips1");
6604 getTargetStreamer().emitDirectiveSetMips1();
6605 break;
6606 case Mips::FeatureMips2:
6607 selectArch("mips2");
6608 getTargetStreamer().emitDirectiveSetMips2();
6609 break;
6610 case Mips::FeatureMips3:
6611 selectArch("mips3");
6612 getTargetStreamer().emitDirectiveSetMips3();
6613 break;
6614 case Mips::FeatureMips4:
6615 selectArch("mips4");
6616 getTargetStreamer().emitDirectiveSetMips4();
6617 break;
6618 case Mips::FeatureMips5:
6619 selectArch("mips5");
6620 getTargetStreamer().emitDirectiveSetMips5();
6621 break;
6622 case Mips::FeatureMips32:
6623 selectArch("mips32");
6624 getTargetStreamer().emitDirectiveSetMips32();
6625 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006626 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006627 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006628 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006629 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006630 case Mips::FeatureMips32r3:
6631 selectArch("mips32r3");
6632 getTargetStreamer().emitDirectiveSetMips32R3();
6633 break;
6634 case Mips::FeatureMips32r5:
6635 selectArch("mips32r5");
6636 getTargetStreamer().emitDirectiveSetMips32R5();
6637 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006638 case Mips::FeatureMips32r6:
6639 selectArch("mips32r6");
6640 getTargetStreamer().emitDirectiveSetMips32R6();
6641 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006642 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006643 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006644 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006645 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006646 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006647 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006648 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006649 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006650 case Mips::FeatureMips64r3:
6651 selectArch("mips64r3");
6652 getTargetStreamer().emitDirectiveSetMips64R3();
6653 break;
6654 case Mips::FeatureMips64r5:
6655 selectArch("mips64r5");
6656 getTargetStreamer().emitDirectiveSetMips64R5();
6657 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006658 case Mips::FeatureMips64r6:
6659 selectArch("mips64r6");
6660 getTargetStreamer().emitDirectiveSetMips64R6();
6661 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006662 }
6663 return false;
6664}
6665
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006666bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006667 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006668 if (getLexer().isNot(AsmToken::Comma)) {
6669 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006670 return Error(Loc, ErrorStr);
6671 }
6672
Matheus Almeida2852af82014-04-22 10:15:54 +00006673 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006674 return true;
6675}
6676
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006677// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
6678// In this class, it is only used for .cprestore.
6679// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
6680// MipsTargetELFStreamer and MipsAsmParser.
6681bool MipsAsmParser::isPicAndNotNxxAbi() {
6682 return inPicMode() && !(isABI_N32() || isABI_N64());
6683}
6684
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006685bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00006686 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00006687 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006688
Toma Tabacudde4c462014-11-06 10:02:45 +00006689 if (inMips16Mode()) {
6690 reportParseError(".cpload is not supported in Mips16 mode");
6691 return false;
6692 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006693
David Blaikie960ea3f2014-06-08 16:18:35 +00006694 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00006695 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006696 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6697 reportParseError("expected register containing function address");
6698 return false;
6699 }
6700
David Blaikie960ea3f2014-06-08 16:18:35 +00006701 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
6702 if (!RegOpnd.isGPRAsmReg()) {
6703 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006704 return false;
6705 }
6706
Toma Tabacudde4c462014-11-06 10:02:45 +00006707 // If this is not the end of the statement, report an error.
6708 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6709 reportParseError("unexpected token, expected end of statement");
6710 return false;
6711 }
6712
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006713 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006714 return false;
6715}
6716
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006717bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
6718 MCAsmParser &Parser = getParser();
6719
6720 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
6721 // is used in non-PIC mode.
6722
6723 if (inMips16Mode()) {
6724 reportParseError(".cprestore is not supported in Mips16 mode");
6725 return false;
6726 }
6727
6728 // Get the stack offset value.
6729 const MCExpr *StackOffset;
6730 int64_t StackOffsetVal;
6731 if (Parser.parseExpression(StackOffset)) {
6732 reportParseError("expected stack offset value");
6733 return false;
6734 }
6735
6736 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
6737 reportParseError("stack offset is not an absolute expression");
6738 return false;
6739 }
6740
6741 if (StackOffsetVal < 0) {
6742 Warning(Loc, ".cprestore with negative stack offset has no effect");
6743 IsCpRestoreSet = false;
6744 } else {
6745 IsCpRestoreSet = true;
6746 CpRestoreOffset = StackOffsetVal;
6747 }
6748
6749 // If this is not the end of the statement, report an error.
6750 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6751 reportParseError("unexpected token, expected end of statement");
6752 return false;
6753 }
6754
Daniel Sandersdf8510d2016-05-11 12:48:19 +00006755 if (!getTargetStreamer().emitDirectiveCpRestore(
6756 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00006757 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006758 Parser.Lex(); // Consume the EndOfStatement.
6759 return false;
6760}
6761
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006762bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006763 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006764 unsigned FuncReg;
6765 unsigned Save;
6766 bool SaveIsReg = true;
6767
Matheus Almeida7e815762014-06-18 13:08:59 +00006768 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006769 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006770 if (ResTy == MatchOperand_NoMatch) {
6771 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00006772 return false;
6773 }
6774
6775 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6776 if (!FuncRegOpnd.isGPRAsmReg()) {
6777 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006778 return false;
6779 }
6780
6781 FuncReg = FuncRegOpnd.getGPR32Reg();
6782 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006783
Toma Tabacu65f10572014-09-16 15:00:52 +00006784 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006785 return true;
6786
Toma Tabacu13964452014-09-04 13:23:44 +00006787 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006788 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00006789 const MCExpr *OffsetExpr;
6790 int64_t OffsetVal;
6791 SMLoc ExprLoc = getLexer().getLoc();
6792
6793 if (Parser.parseExpression(OffsetExpr) ||
6794 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
6795 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00006796 return false;
6797 }
Daniel Sanders5d796282015-09-21 09:26:55 +00006798
6799 Save = OffsetVal;
6800 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00006801 } else {
6802 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6803 if (!SaveOpnd.isGPRAsmReg()) {
6804 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006805 return false;
6806 }
6807 Save = SaveOpnd.getGPR32Reg();
6808 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006809
Toma Tabacu65f10572014-09-16 15:00:52 +00006810 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006811 return true;
6812
Toma Tabacu8874eac2015-02-18 13:46:53 +00006813 const MCExpr *Expr;
6814 if (Parser.parseExpression(Expr)) {
6815 reportParseError("expected expression");
6816 return false;
6817 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006818
Toma Tabacu8874eac2015-02-18 13:46:53 +00006819 if (Expr->getKind() != MCExpr::SymbolRef) {
6820 reportParseError("expected symbol");
6821 return false;
6822 }
6823 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
6824
Daniel Sandersf173dda2015-09-22 10:50:09 +00006825 CpSaveLocation = Save;
6826 CpSaveLocationIsRegister = SaveIsReg;
6827
Toma Tabacu8874eac2015-02-18 13:46:53 +00006828 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
6829 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006830 return false;
6831}
6832
Daniel Sandersf173dda2015-09-22 10:50:09 +00006833bool MipsAsmParser::parseDirectiveCPReturn() {
6834 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
6835 CpSaveLocationIsRegister);
6836 return false;
6837}
6838
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006839bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006840 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006841 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6842 const AsmToken &Tok = Parser.getTok();
6843
6844 if (Tok.getString() == "2008") {
6845 Parser.Lex();
6846 getTargetStreamer().emitDirectiveNaN2008();
6847 return false;
6848 } else if (Tok.getString() == "legacy") {
6849 Parser.Lex();
6850 getTargetStreamer().emitDirectiveNaNLegacy();
6851 return false;
6852 }
6853 }
6854 // If we don't recognize the option passed to the .nan
6855 // directive (e.g. no option or unknown option), emit an error.
6856 reportParseError("invalid option in .nan directive");
6857 return false;
6858}
6859
Jack Carter0b744b32012-10-04 02:29:46 +00006860bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006861 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006862 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00006863 const AsmToken &Tok = Parser.getTok();
6864
6865 if (Tok.getString() == "noat") {
6866 return parseSetNoAtDirective();
6867 } else if (Tok.getString() == "at") {
6868 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00006869 } else if (Tok.getString() == "arch") {
6870 return parseSetArchDirective();
Simon Dardisac9c30c2017-02-01 18:50:24 +00006871 } else if (Tok.getString() == "bopt") {
6872 Warning(Tok.getLoc(), "'bopt' feature is unsupported");
6873 getParser().Lex();
6874 return false;
6875 } else if (Tok.getString() == "nobopt") {
6876 // We're already running in nobopt mode, so nothing to do.
6877 getParser().Lex();
6878 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006879 } else if (Tok.getString() == "fp") {
6880 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006881 } else if (Tok.getString() == "oddspreg") {
6882 return parseSetOddSPRegDirective();
6883 } else if (Tok.getString() == "nooddspreg") {
6884 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006885 } else if (Tok.getString() == "pop") {
6886 return parseSetPopDirective();
6887 } else if (Tok.getString() == "push") {
6888 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00006889 } else if (Tok.getString() == "reorder") {
6890 return parseSetReorderDirective();
6891 } else if (Tok.getString() == "noreorder") {
6892 return parseSetNoReorderDirective();
6893 } else if (Tok.getString() == "macro") {
6894 return parseSetMacroDirective();
6895 } else if (Tok.getString() == "nomacro") {
6896 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00006897 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00006898 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006899 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00006900 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006901 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00006902 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00006903 getTargetStreamer().emitDirectiveSetNoMicroMips();
6904 Parser.eatToEndOfStatement();
6905 return false;
6906 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006907 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00006908 } else if (Tok.getString() == "mips0") {
6909 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00006910 } else if (Tok.getString() == "mips1") {
6911 return parseSetFeature(Mips::FeatureMips1);
6912 } else if (Tok.getString() == "mips2") {
6913 return parseSetFeature(Mips::FeatureMips2);
6914 } else if (Tok.getString() == "mips3") {
6915 return parseSetFeature(Mips::FeatureMips3);
6916 } else if (Tok.getString() == "mips4") {
6917 return parseSetFeature(Mips::FeatureMips4);
6918 } else if (Tok.getString() == "mips5") {
6919 return parseSetFeature(Mips::FeatureMips5);
6920 } else if (Tok.getString() == "mips32") {
6921 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00006922 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006923 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006924 } else if (Tok.getString() == "mips32r3") {
6925 return parseSetFeature(Mips::FeatureMips32r3);
6926 } else if (Tok.getString() == "mips32r5") {
6927 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006928 } else if (Tok.getString() == "mips32r6") {
6929 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006930 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006931 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006932 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006933 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006934 } else if (Tok.getString() == "mips64r3") {
6935 return parseSetFeature(Mips::FeatureMips64r3);
6936 } else if (Tok.getString() == "mips64r5") {
6937 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006938 } else if (Tok.getString() == "mips64r6") {
6939 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00006940 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006941 return parseSetFeature(Mips::FeatureDSP);
Petar Jovanovic65f10242017-10-05 17:40:32 +00006942 } else if (Tok.getString() == "dspr2") {
6943 return parseSetFeature(Mips::FeatureDSPR2);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006944 } else if (Tok.getString() == "nodsp") {
6945 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00006946 } else if (Tok.getString() == "msa") {
6947 return parseSetMsaDirective();
6948 } else if (Tok.getString() == "nomsa") {
6949 return parseSetNoMsaDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +00006950 } else if (Tok.getString() == "mt") {
6951 return parseSetMtDirective();
6952 } else if (Tok.getString() == "nomt") {
6953 return parseSetNoMtDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00006954 } else if (Tok.getString() == "softfloat") {
6955 return parseSetSoftFloatDirective();
6956 } else if (Tok.getString() == "hardfloat") {
6957 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00006958 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00006959 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00006960 parseSetAssignment();
6961 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006962 }
Jack Carter07c818d2013-01-25 01:31:34 +00006963
Jack Carter0b744b32012-10-04 02:29:46 +00006964 return true;
6965}
6966
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006967/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00006968/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006969bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006970 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006971 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006972 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00006973 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00006974 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00006975 return true;
6976
6977 getParser().getStreamer().EmitValue(Value, Size);
6978
6979 if (getLexer().is(AsmToken::EndOfStatement))
6980 break;
6981
Jack Carter07c818d2013-01-25 01:31:34 +00006982 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006983 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00006984 Parser.Lex();
6985 }
6986 }
6987
6988 Parser.Lex();
6989 return false;
6990}
6991
Vladimir Medic4c299852013-11-06 11:27:05 +00006992/// parseDirectiveGpWord
6993/// ::= .gpword local_sym
6994bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006995 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00006996 const MCExpr *Value;
6997 // EmitGPRel32Value requires an expression, so we are using base class
6998 // method to evaluate the expression.
6999 if (getParser().parseExpression(Value))
7000 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00007001 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00007002
Vladimir Medice10c1122013-11-13 13:18:04 +00007003 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00007004 return Error(getLexer().getLoc(),
7005 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00007006 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00007007 return false;
7008}
7009
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007010/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00007011/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007012bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007013 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007014 const MCExpr *Value;
7015 // EmitGPRel64Value requires an expression, so we are using base class
7016 // method to evaluate the expression.
7017 if (getParser().parseExpression(Value))
7018 return true;
7019 getParser().getStreamer().EmitGPRel64Value(Value);
7020
7021 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007022 return Error(getLexer().getLoc(),
7023 "unexpected token, expected end of statement");
7024 Parser.Lex(); // Eat EndOfStatement token.
7025 return false;
7026}
7027
7028/// parseDirectiveDtpRelWord
7029/// ::= .dtprelword tls_sym
7030bool MipsAsmParser::parseDirectiveDtpRelWord() {
7031 MCAsmParser &Parser = getParser();
7032 const MCExpr *Value;
7033 // EmitDTPRel32Value requires an expression, so we are using base class
7034 // method to evaluate the expression.
7035 if (getParser().parseExpression(Value))
7036 return true;
7037 getParser().getStreamer().EmitDTPRel32Value(Value);
7038
7039 if (getLexer().isNot(AsmToken::EndOfStatement))
7040 return Error(getLexer().getLoc(),
7041 "unexpected token, expected end of statement");
7042 Parser.Lex(); // Eat EndOfStatement token.
7043 return false;
7044}
7045
7046/// parseDirectiveDtpRelDWord
7047/// ::= .dtpreldword tls_sym
7048bool MipsAsmParser::parseDirectiveDtpRelDWord() {
7049 MCAsmParser &Parser = getParser();
7050 const MCExpr *Value;
7051 // EmitDTPRel64Value requires an expression, so we are using base class
7052 // method to evaluate the expression.
7053 if (getParser().parseExpression(Value))
7054 return true;
7055 getParser().getStreamer().EmitDTPRel64Value(Value);
7056
7057 if (getLexer().isNot(AsmToken::EndOfStatement))
7058 return Error(getLexer().getLoc(),
7059 "unexpected token, expected end of statement");
7060 Parser.Lex(); // Eat EndOfStatement token.
7061 return false;
7062}
7063
7064/// parseDirectiveTpRelWord
7065/// ::= .tprelword tls_sym
7066bool MipsAsmParser::parseDirectiveTpRelWord() {
7067 MCAsmParser &Parser = getParser();
7068 const MCExpr *Value;
7069 // EmitTPRel32Value requires an expression, so we are using base class
7070 // method to evaluate the expression.
7071 if (getParser().parseExpression(Value))
7072 return true;
7073 getParser().getStreamer().EmitTPRel32Value(Value);
7074
7075 if (getLexer().isNot(AsmToken::EndOfStatement))
7076 return Error(getLexer().getLoc(),
7077 "unexpected token, expected end of statement");
7078 Parser.Lex(); // Eat EndOfStatement token.
7079 return false;
7080}
7081
7082/// parseDirectiveTpRelDWord
7083/// ::= .tpreldword tls_sym
7084bool MipsAsmParser::parseDirectiveTpRelDWord() {
7085 MCAsmParser &Parser = getParser();
7086 const MCExpr *Value;
7087 // EmitTPRel64Value requires an expression, so we are using base class
7088 // method to evaluate the expression.
7089 if (getParser().parseExpression(Value))
7090 return true;
7091 getParser().getStreamer().EmitTPRel64Value(Value);
7092
7093 if (getLexer().isNot(AsmToken::EndOfStatement))
7094 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007095 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00007096 Parser.Lex(); // Eat EndOfStatement token.
7097 return false;
7098}
7099
Jack Carter0cd3c192014-01-06 23:27:31 +00007100bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007101 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00007102 // Get the option token.
7103 AsmToken Tok = Parser.getTok();
7104 // At the moment only identifiers are supported.
7105 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007106 return Error(Parser.getTok().getLoc(),
7107 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00007108 }
7109
7110 StringRef Option = Tok.getIdentifier();
7111
7112 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007113 // MipsAsmParser needs to know if the current PIC mode changes.
7114 IsPicEnabled = false;
7115
Jack Carter0cd3c192014-01-06 23:27:31 +00007116 getTargetStreamer().emitDirectiveOptionPic0();
7117 Parser.Lex();
7118 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007119 return Error(Parser.getTok().getLoc(),
7120 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007121 }
7122 return false;
7123 }
7124
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007125 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007126 // MipsAsmParser needs to know if the current PIC mode changes.
7127 IsPicEnabled = true;
7128
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007129 getTargetStreamer().emitDirectiveOptionPic2();
7130 Parser.Lex();
7131 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007132 return Error(Parser.getTok().getLoc(),
7133 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007134 }
7135 return false;
7136 }
7137
Jack Carter0cd3c192014-01-06 23:27:31 +00007138 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00007139 Warning(Parser.getTok().getLoc(),
7140 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007141 Parser.eatToEndOfStatement();
7142 return false;
7143}
7144
Toma Tabacu9ca50962015-04-16 09:53:47 +00007145/// parseInsnDirective
7146/// ::= .insn
7147bool MipsAsmParser::parseInsnDirective() {
7148 // If this is not the end of the statement, report an error.
7149 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7150 reportParseError("unexpected token, expected end of statement");
7151 return false;
7152 }
7153
7154 // The actual label marking happens in
7155 // MipsELFStreamer::createPendingLabelRelocs().
7156 getTargetStreamer().emitDirectiveInsn();
7157
7158 getParser().Lex(); // Eat EndOfStatement token.
7159 return false;
7160}
7161
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007162/// parseRSectionDirective
7163/// ::= .rdata
7164bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
7165 // If this is not the end of the statement, report an error.
7166 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7167 reportParseError("unexpected token, expected end of statement");
7168 return false;
7169 }
7170
7171 MCSection *ELFSection = getContext().getELFSection(
7172 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7173 getParser().getStreamer().SwitchSection(ELFSection);
7174
7175 getParser().Lex(); // Eat EndOfStatement token.
7176 return false;
7177}
7178
Simon Atanasyanbe186202016-02-11 06:45:54 +00007179/// parseSSectionDirective
7180/// ::= .sbss
7181/// ::= .sdata
7182bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7183 // If this is not the end of the statement, report an error.
7184 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7185 reportParseError("unexpected token, expected end of statement");
7186 return false;
7187 }
7188
7189 MCSection *ELFSection = getContext().getELFSection(
7190 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7191 getParser().getStreamer().SwitchSection(ELFSection);
7192
7193 getParser().Lex(); // Eat EndOfStatement token.
7194 return false;
7195}
7196
Daniel Sanders7e527422014-07-10 13:38:23 +00007197/// parseDirectiveModule
7198/// ::= .module oddspreg
7199/// ::= .module nooddspreg
7200/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007201/// ::= .module softfloat
7202/// ::= .module hardfloat
Simon Dardis805f1e02017-07-11 21:28:36 +00007203/// ::= .module mt
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007204bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007205 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007206 MCAsmLexer &Lexer = getLexer();
7207 SMLoc L = Lexer.getLoc();
7208
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007209 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007210 // TODO : get a better message.
7211 reportParseError(".module directive must appear before any code");
7212 return false;
7213 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007214
Toma Tabacuc405c822015-01-23 10:40:19 +00007215 StringRef Option;
7216 if (Parser.parseIdentifier(Option)) {
7217 reportParseError("expected .module option identifier");
7218 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007219 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007220
Toma Tabacuc405c822015-01-23 10:40:19 +00007221 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007222 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007223
Toma Tabacu3c499582015-06-25 10:56:57 +00007224 // Synchronize the abiflags information with the FeatureBits information we
7225 // changed above.
7226 getTargetStreamer().updateABIInfo(*this);
7227
7228 // If printing assembly, use the recently updated abiflags information.
7229 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7230 // emitted at the end).
7231 getTargetStreamer().emitDirectiveModuleOddSPReg();
7232
Toma Tabacuc405c822015-01-23 10:40:19 +00007233 // If this is not the end of the statement, report an error.
7234 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7235 reportParseError("unexpected token, expected end of statement");
7236 return false;
7237 }
7238
7239 return false; // parseDirectiveModule has finished successfully.
7240 } else if (Option == "nooddspreg") {
7241 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007242 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007243 }
7244
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007245 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007246
Toma Tabacu3c499582015-06-25 10:56:57 +00007247 // Synchronize the abiflags information with the FeatureBits information we
7248 // changed above.
7249 getTargetStreamer().updateABIInfo(*this);
7250
7251 // If printing assembly, use the recently updated abiflags information.
7252 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7253 // emitted at the end).
7254 getTargetStreamer().emitDirectiveModuleOddSPReg();
7255
Toma Tabacuc405c822015-01-23 10:40:19 +00007256 // If this is not the end of the statement, report an error.
7257 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7258 reportParseError("unexpected token, expected end of statement");
7259 return false;
7260 }
7261
7262 return false; // parseDirectiveModule has finished successfully.
7263 } else if (Option == "fp") {
7264 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007265 } else if (Option == "softfloat") {
7266 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7267
7268 // Synchronize the ABI Flags information with the FeatureBits information we
7269 // updated above.
7270 getTargetStreamer().updateABIInfo(*this);
7271
7272 // If printing assembly, use the recently updated ABI Flags information.
7273 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7274 // emitted later).
7275 getTargetStreamer().emitDirectiveModuleSoftFloat();
7276
7277 // If this is not the end of the statement, report an error.
7278 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7279 reportParseError("unexpected token, expected end of statement");
7280 return false;
7281 }
7282
7283 return false; // parseDirectiveModule has finished successfully.
7284 } else if (Option == "hardfloat") {
7285 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7286
7287 // Synchronize the ABI Flags information with the FeatureBits information we
7288 // updated above.
7289 getTargetStreamer().updateABIInfo(*this);
7290
7291 // If printing assembly, use the recently updated ABI Flags information.
7292 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7293 // emitted later).
7294 getTargetStreamer().emitDirectiveModuleHardFloat();
7295
7296 // If this is not the end of the statement, report an error.
7297 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7298 reportParseError("unexpected token, expected end of statement");
7299 return false;
7300 }
7301
7302 return false; // parseDirectiveModule has finished successfully.
Simon Dardis805f1e02017-07-11 21:28:36 +00007303 } else if (Option == "mt") {
7304 setModuleFeatureBits(Mips::FeatureMT, "mt");
7305
7306 // Synchronize the ABI Flags information with the FeatureBits information we
7307 // updated above.
7308 getTargetStreamer().updateABIInfo(*this);
7309
Simon Dardisd9611922017-07-11 21:36:58 +00007310 // If printing assembly, use the recently updated ABI Flags information.
Simon Dardis805f1e02017-07-11 21:28:36 +00007311 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7312 // emitted later).
7313 getTargetStreamer().emitDirectiveModuleMT();
7314
7315 // If this is not the end of the statement, report an error.
7316 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7317 reportParseError("unexpected token, expected end of statement");
7318 return false;
7319 }
7320
7321 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007322 } else {
7323 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7324 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007325}
7326
7327/// parseDirectiveModuleFP
7328/// ::= =32
7329/// ::= =xx
7330/// ::= =64
7331bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007332 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007333 MCAsmLexer &Lexer = getLexer();
7334
7335 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007336 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007337 return false;
7338 }
7339 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007340
Daniel Sanders7e527422014-07-10 13:38:23 +00007341 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007342 if (!parseFpABIValue(FpABI, ".module"))
7343 return false;
7344
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007345 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007346 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007347 return false;
7348 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007349
Toma Tabacua64e5402015-06-25 12:44:38 +00007350 // Synchronize the abiflags information with the FeatureBits information we
7351 // changed above.
7352 getTargetStreamer().updateABIInfo(*this);
7353
7354 // If printing assembly, use the recently updated abiflags information.
7355 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7356 // emitted at the end).
7357 getTargetStreamer().emitDirectiveModuleFP();
7358
Daniel Sanders7e527422014-07-10 13:38:23 +00007359 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007360 return false;
7361}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007362
Daniel Sanders7e527422014-07-10 13:38:23 +00007363bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007364 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007365 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007366 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007367 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007368
7369 if (Lexer.is(AsmToken::Identifier)) {
7370 StringRef Value = Parser.getTok().getString();
7371 Parser.Lex();
7372
7373 if (Value != "xx") {
7374 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7375 return false;
7376 }
7377
7378 if (!isABI_O32()) {
7379 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7380 return false;
7381 }
7382
Daniel Sanders7e527422014-07-10 13:38:23 +00007383 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007384 if (ModuleLevelOptions) {
7385 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7386 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7387 } else {
7388 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7389 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7390 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007391 return true;
7392 }
7393
7394 if (Lexer.is(AsmToken::Integer)) {
7395 unsigned Value = Parser.getTok().getIntVal();
7396 Parser.Lex();
7397
7398 if (Value != 32 && Value != 64) {
7399 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7400 return false;
7401 }
7402
7403 if (Value == 32) {
7404 if (!isABI_O32()) {
7405 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7406 return false;
7407 }
7408
Daniel Sanders7e527422014-07-10 13:38:23 +00007409 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007410 if (ModuleLevelOptions) {
7411 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7412 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7413 } else {
7414 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7415 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7416 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007417 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007418 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007419 if (ModuleLevelOptions) {
7420 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7421 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7422 } else {
7423 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7424 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7425 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007426 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007427
Daniel Sanders7e527422014-07-10 13:38:23 +00007428 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007429 }
7430
7431 return false;
7432}
7433
Jack Carter0b744b32012-10-04 02:29:46 +00007434bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007435 // This returns false if this function recognizes the directive
7436 // regardless of whether it is successfully handles or reports an
7437 // error. Otherwise it returns true to give the generic parser a
7438 // chance at recognizing it.
7439
Rafael Espindola961d4692014-11-11 05:18:41 +00007440 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007441 StringRef IDVal = DirectiveID.getString();
7442
Nirav Dave996fc132016-05-05 14:15:46 +00007443 if (IDVal == ".cpload") {
7444 parseDirectiveCpLoad(DirectiveID.getLoc());
7445 return false;
7446 }
7447 if (IDVal == ".cprestore") {
7448 parseDirectiveCpRestore(DirectiveID.getLoc());
7449 return false;
7450 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00007451 if (IDVal == ".dword") {
7452 parseDataDirective(8, DirectiveID.getLoc());
7453 return false;
7454 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007455 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007456 StringRef SymbolName;
7457
7458 if (Parser.parseIdentifier(SymbolName)) {
7459 reportParseError("expected identifier after .ent");
7460 return false;
7461 }
7462
7463 // There's an undocumented extension that allows an integer to
7464 // follow the name of the procedure which AFAICS is ignored by GAS.
7465 // Example: .ent foo,2
7466 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7467 if (getLexer().isNot(AsmToken::Comma)) {
7468 // Even though we accept this undocumented extension for compatibility
7469 // reasons, the additional integer argument does not actually change
7470 // the behaviour of the '.ent' directive, so we would like to discourage
7471 // its use. We do this by not referring to the extended version in
7472 // error messages which are not directly related to its use.
7473 reportParseError("unexpected token, expected end of statement");
7474 return false;
7475 }
7476 Parser.Lex(); // Eat the comma.
7477 const MCExpr *DummyNumber;
7478 int64_t DummyNumberVal;
7479 // If the user was explicitly trying to use the extended version,
7480 // we still give helpful extension-related error messages.
7481 if (Parser.parseExpression(DummyNumber)) {
7482 reportParseError("expected number after comma");
7483 return false;
7484 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007485 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007486 reportParseError("expected an absolute expression after comma");
7487 return false;
7488 }
7489 }
7490
7491 // If this is not the end of the statement, report an error.
7492 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7493 reportParseError("unexpected token, expected end of statement");
7494 return false;
7495 }
7496
Jim Grosbach6f482002015-05-18 18:43:14 +00007497 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007498
7499 getTargetStreamer().emitDirectiveEnt(*Sym);
7500 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007501 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007502 return false;
7503 }
7504
Jack Carter07c818d2013-01-25 01:31:34 +00007505 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007506 StringRef SymbolName;
7507
7508 if (Parser.parseIdentifier(SymbolName)) {
7509 reportParseError("expected identifier after .end");
7510 return false;
7511 }
7512
7513 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7514 reportParseError("unexpected token, expected end of statement");
7515 return false;
7516 }
7517
7518 if (CurrentFn == nullptr) {
7519 reportParseError(".end used without .ent");
7520 return false;
7521 }
7522
7523 if ((SymbolName != CurrentFn->getName())) {
7524 reportParseError(".end symbol does not match .ent symbol");
7525 return false;
7526 }
7527
7528 getTargetStreamer().emitDirectiveEnd(SymbolName);
7529 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007530 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007531 return false;
7532 }
7533
Jack Carter07c818d2013-01-25 01:31:34 +00007534 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007535 // .frame $stack_reg, frame_size_in_bytes, $return_reg
7536 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007537 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007538 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7539 reportParseError("expected stack register");
7540 return false;
7541 }
7542
7543 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7544 if (!StackRegOpnd.isGPRAsmReg()) {
7545 reportParseError(StackRegOpnd.getStartLoc(),
7546 "expected general purpose register");
7547 return false;
7548 }
7549 unsigned StackReg = StackRegOpnd.getGPR32Reg();
7550
7551 if (Parser.getTok().is(AsmToken::Comma))
7552 Parser.Lex();
7553 else {
7554 reportParseError("unexpected token, expected comma");
7555 return false;
7556 }
7557
7558 // Parse the frame size.
7559 const MCExpr *FrameSize;
7560 int64_t FrameSizeVal;
7561
7562 if (Parser.parseExpression(FrameSize)) {
7563 reportParseError("expected frame size value");
7564 return false;
7565 }
7566
Jim Grosbach13760bd2015-05-30 01:25:56 +00007567 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007568 reportParseError("frame size not an absolute expression");
7569 return false;
7570 }
7571
7572 if (Parser.getTok().is(AsmToken::Comma))
7573 Parser.Lex();
7574 else {
7575 reportParseError("unexpected token, expected comma");
7576 return false;
7577 }
7578
7579 // Parse the return register.
7580 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00007581 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007582 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7583 reportParseError("expected return register");
7584 return false;
7585 }
7586
7587 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7588 if (!ReturnRegOpnd.isGPRAsmReg()) {
7589 reportParseError(ReturnRegOpnd.getStartLoc(),
7590 "expected general purpose register");
7591 return false;
7592 }
7593
7594 // If this is not the end of the statement, report an error.
7595 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7596 reportParseError("unexpected token, expected end of statement");
7597 return false;
7598 }
7599
7600 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
7601 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007602 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007603 return false;
7604 }
7605
Jack Carter07c818d2013-01-25 01:31:34 +00007606 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00007607 parseDirectiveSet();
7608 return false;
Jack Carterbe332172012-09-07 00:48:02 +00007609 }
7610
Daniel Sandersd97a6342014-08-13 10:07:34 +00007611 if (IDVal == ".mask" || IDVal == ".fmask") {
7612 // .mask bitmask, frame_offset
7613 // bitmask: One bit for each register used.
7614 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
7615 // first register is expected to be saved.
7616 // Examples:
7617 // .mask 0x80000000, -4
7618 // .fmask 0x80000000, -4
7619 //
Jack Carterbe332172012-09-07 00:48:02 +00007620
Daniel Sandersd97a6342014-08-13 10:07:34 +00007621 // Parse the bitmask
7622 const MCExpr *BitMask;
7623 int64_t BitMaskVal;
7624
7625 if (Parser.parseExpression(BitMask)) {
7626 reportParseError("expected bitmask value");
7627 return false;
7628 }
7629
Jim Grosbach13760bd2015-05-30 01:25:56 +00007630 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007631 reportParseError("bitmask not an absolute expression");
7632 return false;
7633 }
7634
7635 if (Parser.getTok().is(AsmToken::Comma))
7636 Parser.Lex();
7637 else {
7638 reportParseError("unexpected token, expected comma");
7639 return false;
7640 }
7641
7642 // Parse the frame_offset
7643 const MCExpr *FrameOffset;
7644 int64_t FrameOffsetVal;
7645
7646 if (Parser.parseExpression(FrameOffset)) {
7647 reportParseError("expected frame offset value");
7648 return false;
7649 }
7650
Jim Grosbach13760bd2015-05-30 01:25:56 +00007651 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007652 reportParseError("frame offset not an absolute expression");
7653 return false;
7654 }
7655
7656 // If this is not the end of the statement, report an error.
7657 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7658 reportParseError("unexpected token, expected end of statement");
7659 return false;
7660 }
7661
7662 if (IDVal == ".mask")
7663 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
7664 else
7665 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00007666 return false;
7667 }
7668
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007669 if (IDVal == ".nan")
7670 return parseDirectiveNaN();
7671
Jack Carter07c818d2013-01-25 01:31:34 +00007672 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00007673 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00007674 return false;
7675 }
7676
Rafael Espindolab59fb732014-03-28 18:50:26 +00007677 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007678 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007679 return false;
7680 }
7681
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007682 if (IDVal == ".dtprelword") {
7683 parseDirectiveDtpRelWord();
7684 return false;
7685 }
7686
7687 if (IDVal == ".dtpreldword") {
7688 parseDirectiveDtpRelDWord();
7689 return false;
7690 }
7691
7692 if (IDVal == ".tprelword") {
7693 parseDirectiveTpRelWord();
7694 return false;
7695 }
7696
7697 if (IDVal == ".tpreldword") {
7698 parseDirectiveTpRelDWord();
7699 return false;
7700 }
7701
Jack Carter07c818d2013-01-25 01:31:34 +00007702 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007703 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00007704 return false;
7705 }
7706
Scott Egertond1aeb052016-02-15 16:11:51 +00007707 if (IDVal == ".hword") {
7708 parseDataDirective(2, DirectiveID.getLoc());
7709 return false;
7710 }
7711
Nirav Dave996fc132016-05-05 14:15:46 +00007712 if (IDVal == ".option") {
7713 parseDirectiveOption();
7714 return false;
7715 }
Jack Carter0cd3c192014-01-06 23:27:31 +00007716
7717 if (IDVal == ".abicalls") {
7718 getTargetStreamer().emitDirectiveAbiCalls();
7719 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007720 Error(Parser.getTok().getLoc(),
7721 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007722 }
7723 return false;
7724 }
7725
Nirav Dave996fc132016-05-05 14:15:46 +00007726 if (IDVal == ".cpsetup") {
7727 parseDirectiveCPSetup();
7728 return false;
7729 }
7730 if (IDVal == ".cpreturn") {
7731 parseDirectiveCPReturn();
7732 return false;
7733 }
7734 if (IDVal == ".module") {
7735 parseDirectiveModule();
7736 return false;
7737 }
7738 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
7739 parseInternalDirectiveReallowModule();
7740 return false;
7741 }
7742 if (IDVal == ".insn") {
7743 parseInsnDirective();
7744 return false;
7745 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007746 if (IDVal == ".rdata") {
7747 parseRSectionDirective(".rodata");
7748 return false;
7749 }
Nirav Dave996fc132016-05-05 14:15:46 +00007750 if (IDVal == ".sbss") {
7751 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
7752 return false;
7753 }
7754 if (IDVal == ".sdata") {
7755 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
7756 return false;
7757 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00007758
Rafael Espindola870c4e92012-01-11 03:56:41 +00007759 return true;
7760}
7761
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00007762bool MipsAsmParser::parseInternalDirectiveReallowModule() {
7763 // If this is not the end of the statement, report an error.
7764 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7765 reportParseError("unexpected token, expected end of statement");
7766 return false;
7767 }
7768
7769 getTargetStreamer().reallowModuleDirective();
7770
7771 getParser().Lex(); // Eat EndOfStatement token.
7772 return false;
7773}
7774
Rafael Espindola870c4e92012-01-11 03:56:41 +00007775extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00007776 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
7777 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
7778 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
7779 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00007780}
Jack Carterb4dbc172012-09-05 23:34:03 +00007781
7782#define GET_REGISTER_MATCHER
7783#define GET_MATCHER_IMPLEMENTATION
7784#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00007785
7786bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
7787 // Find the appropriate table for this asm variant.
7788 const MatchEntry *Start, *End;
7789 switch (VariantID) {
7790 default: llvm_unreachable("invalid variant!");
7791 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
7792 }
7793 // Search the table.
7794 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
7795 return MnemonicRange.first != MnemonicRange.second;
7796}