blob: 4a1d585bbbcdcea73f232e46bab72a9bf6923d01 [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();
Jack Carter0b744b32012-10-04 02:29:46 +0000346
Jack Carterd76b2372013-03-21 21:44:16 +0000347 bool parseSetAssignment();
348
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000349 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000350 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000351 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000352 bool parseDirectiveDtpRelWord();
353 bool parseDirectiveDtpRelDWord();
354 bool parseDirectiveTpRelWord();
355 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000356 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000357 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000358 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
359 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000360
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000361 bool parseInternalDirectiveReallowModule();
362
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000363 bool eatComma(StringRef ErrorStr);
364
Jack Carter1ac53222013-02-20 23:11:17 +0000365 int matchCPURegisterName(StringRef Symbol);
366
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000367 int matchHWRegsRegisterName(StringRef Symbol);
368
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000369 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000370
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000371 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000372
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000373 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000374
Jack Carter5dc8ac92013-09-25 23:50:44 +0000375 int matchMSA128RegisterName(StringRef Name);
376
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000377 int matchMSA128CtrlRegisterName(StringRef Name);
378
Jack Carterd0bd6422013-04-18 00:41:53 +0000379 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000380
Toma Tabacu89a712b2015-04-15 10:48:56 +0000381 /// Returns the internal register number for the current AT. Also checks if
382 /// the current AT is unavailable (set to $0) and gives an error if it is.
383 /// This should be used in pseudo-instruction expansions which need AT.
384 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000385
Simon Dardis3aa8a902017-02-06 12:43:46 +0000386 bool canUseATReg();
387
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000388 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
389 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000390
391 // Helper function that checks if the value of a vector index is within the
392 // boundaries of accepted values for each RegisterKind
393 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
394 bool validateMSAIndex(int Val, int RegKind);
395
Daniel Sandersf0df2212014-08-04 12:20:00 +0000396 // Selects a new architecture by updating the FeatureBits with the necessary
397 // info including implied dependencies.
398 // Internally, it clears all the feature bits related to *any* architecture
399 // and selects the new one using the ToggleFeature functionality of the
400 // MCSubtargetInfo object that handles implied dependencies. The reason we
401 // clear all the arch related bits manually is because ToggleFeature only
402 // clears the features that imply the feature being cleared and not the
403 // features implied by the feature being cleared. This is easier to see
404 // with an example:
405 // --------------------------------------------------
406 // | Feature | Implies |
407 // | -------------------------------------------------|
408 // | FeatureMips1 | None |
409 // | FeatureMips2 | FeatureMips1 |
410 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
411 // | FeatureMips4 | FeatureMips3 |
412 // | ... | |
413 // --------------------------------------------------
414 //
415 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
416 // FeatureMipsGP64 | FeatureMips1)
417 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
418 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000419 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000420 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000421 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
422 STI.setFeatureBits(FeatureBits);
423 setAvailableFeatures(
424 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000425 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000426 }
427
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000428 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000429 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000430 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000431 setAvailableFeatures(
432 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000433 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000434 }
435 }
436
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000437 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000438 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000439 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000440 setAvailableFeatures(
441 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000442 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000443 }
444 }
445
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000446 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
447 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000448 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000449 }
450
451 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
452 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000453 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000454 }
455
Rafael Espindola870c4e92012-01-11 03:56:41 +0000456public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000457 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000458 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000459 Match_RequiresDifferentOperands,
460 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000461 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000462 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000463 Match_NonZeroOperandForSync,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000464#define GET_OPERAND_DIAGNOSTIC_TYPES
465#include "MipsGenAsmMatcher.inc"
466#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000467 };
468
Akira Hatanakab11ef082015-11-14 06:35:56 +0000469 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000470 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000471 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000472 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
473 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000474 MCAsmParserExtension::Initialize(parser);
475
Toma Tabacu11e14a92015-04-21 11:50:52 +0000476 parser.addAliasForDirective(".asciiz", ".asciz");
477
Jack Carterb4dbc172012-09-05 23:34:03 +0000478 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000479 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000480
Toma Tabacu9db22db2014-09-09 10:15:38 +0000481 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000482 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000483 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000484
Toma Tabacu9db22db2014-09-09 10:15:38 +0000485 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000486 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000487 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000488
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000489 getTargetStreamer().updateABIInfo(*this);
490
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000491 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000492 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000493
494 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000495
Rafael Espindola699281c2016-05-18 11:58:50 +0000496 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000497
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000498 IsCpRestoreSet = false;
499 CpRestoreOffset = -1;
500
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000501 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000502 if ((TheTriple.getArch() == Triple::mips) ||
503 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000504 IsLittleEndian = false;
505 else
506 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000507 }
508
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000509 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
510 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
511
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000512 bool isGP64bit() const {
513 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
514 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000515
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000516 bool isFP64bit() const {
517 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
518 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000519
Eric Christophera5762812015-01-26 17:33:46 +0000520 const MipsABIInfo &getABI() const { return ABI; }
521 bool isABI_N32() const { return ABI.IsN32(); }
522 bool isABI_N64() const { return ABI.IsN64(); }
523 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000524 bool isABI_FPXX() const {
525 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
526 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000527
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000528 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000529 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000530 }
531
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000532 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000533 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000534 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000535
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000536 bool hasMips1() const {
537 return getSTI().getFeatureBits()[Mips::FeatureMips1];
538 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000539
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000540 bool hasMips2() const {
541 return getSTI().getFeatureBits()[Mips::FeatureMips2];
542 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000543
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 bool hasMips3() const {
545 return getSTI().getFeatureBits()[Mips::FeatureMips3];
546 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000547
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000548 bool hasMips4() const {
549 return getSTI().getFeatureBits()[Mips::FeatureMips4];
550 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000551
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000552 bool hasMips5() const {
553 return getSTI().getFeatureBits()[Mips::FeatureMips5];
554 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000555
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000556 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000557 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000558 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000559
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000560 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000561 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000562 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000563
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000564 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000565 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000566 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000567
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000568 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000569 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000570 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000571
Daniel Sanders17793142015-02-18 16:24:50 +0000572 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000573 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000574 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000575
Daniel Sanders17793142015-02-18 16:24:50 +0000576 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000577 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000578 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000579
Daniel Sanders17793142015-02-18 16:24:50 +0000580 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000581 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000582 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000583
Daniel Sanders17793142015-02-18 16:24:50 +0000584 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000585 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000586 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000587
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000588 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000589 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000590 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000591
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000592 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000593 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000594 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000595
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000596 bool hasDSP() const {
597 return getSTI().getFeatureBits()[Mips::FeatureDSP];
598 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000599
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000600 bool hasDSPR2() const {
601 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
602 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000603
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000604 bool hasDSPR3() const {
605 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
606 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000607
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000608 bool hasMSA() const {
609 return getSTI().getFeatureBits()[Mips::FeatureMSA];
610 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000611
Kai Nackee0245392015-01-27 19:11:28 +0000612 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000613 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000614 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000615
Daniel Sandersa6994442015-08-18 12:33:54 +0000616 bool inPicMode() {
617 return IsPicEnabled;
618 }
619
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000620 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000621 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000622 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000623
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000624 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000625 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000626 }
627
Eric Christophere8ae3e32015-05-07 23:10:21 +0000628 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000629 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000630 }
Simon Dardisae719c52017-07-11 18:03:20 +0000631 bool hasMT() const {
632 return getSTI().getFeatureBits()[Mips::FeatureMT];
633 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000634
Toma Tabacud9d344b2015-04-27 14:05:04 +0000635 /// Warn if RegIndex is the same as the current AT.
636 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000637
638 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000639
640 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000641
642 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
643 AsmToken::TokenKind OperatorToken,
644 MCContext &Ctx) override {
645 switch(OperatorToken) {
646 default:
647 llvm_unreachable("Unknown token");
648 return nullptr;
649 case AsmToken::PercentCall16:
650 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
651 case AsmToken::PercentCall_Hi:
652 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
653 case AsmToken::PercentCall_Lo:
654 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
655 case AsmToken::PercentDtprel_Hi:
656 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
657 case AsmToken::PercentDtprel_Lo:
658 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
659 case AsmToken::PercentGot:
660 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
661 case AsmToken::PercentGot_Disp:
662 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
663 case AsmToken::PercentGot_Hi:
664 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
665 case AsmToken::PercentGot_Lo:
666 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
667 case AsmToken::PercentGot_Ofst:
668 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
669 case AsmToken::PercentGot_Page:
670 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
671 case AsmToken::PercentGottprel:
672 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
673 case AsmToken::PercentGp_Rel:
674 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
675 case AsmToken::PercentHi:
676 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
677 case AsmToken::PercentHigher:
678 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
679 case AsmToken::PercentHighest:
680 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
681 case AsmToken::PercentLo:
682 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
683 case AsmToken::PercentNeg:
684 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
685 case AsmToken::PercentPcrel_Hi:
686 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
687 case AsmToken::PercentPcrel_Lo:
688 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
689 case AsmToken::PercentTlsgd:
690 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
691 case AsmToken::PercentTlsldm:
692 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
693 case AsmToken::PercentTprel_Hi:
694 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
695 case AsmToken::PercentTprel_Lo:
696 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
697 }
698 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000699};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000700
701/// MipsOperand - Instances of this class represent a parsed Mips machine
702/// instruction.
703class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000704public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000705 /// Broad categories of register classes
706 /// The exact class is finalized by the render method.
707 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000708 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000709 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000710 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000711 RegKind_FCC = 4, /// FCC
712 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
713 RegKind_MSACtrl = 16, /// MSA control registers
714 RegKind_COP2 = 32, /// COP2
715 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
716 /// context).
717 RegKind_CCR = 128, /// CCR
718 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000719 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000720 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000721 /// Potentially any (e.g. $1)
722 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
723 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000724 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000725 };
726
727private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000728 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000729 k_Immediate, /// An immediate (possibly involving symbol references)
730 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000731 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000732 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000733 k_RegList, /// A physical register list
734 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000735 } Kind;
736
David Blaikie960ea3f2014-06-08 16:18:35 +0000737public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000738 MipsOperand(KindTy K, MipsAsmParser &Parser)
739 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
740
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000741 ~MipsOperand() override {
742 switch (Kind) {
743 case k_Immediate:
744 break;
745 case k_Memory:
746 delete Mem.Base;
747 break;
748 case k_RegList:
749 delete RegList.List;
750 case k_RegisterIndex:
751 case k_Token:
752 case k_RegPair:
753 break;
754 }
755 }
756
David Blaikie960ea3f2014-06-08 16:18:35 +0000757private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000758 /// For diagnostics, and checking the assembler temporary
759 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000760
Eric Christopher8996c5d2013-03-15 00:42:55 +0000761 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000762 const char *Data;
763 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000764 };
765
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000766 struct RegIdxOp {
767 unsigned Index; /// Index into the register class
768 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000769 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000770 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000771 };
772
773 struct ImmOp {
774 const MCExpr *Val;
775 };
776
777 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000778 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000779 const MCExpr *Off;
780 };
781
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000782 struct RegListOp {
783 SmallVector<unsigned, 10> *List;
784 };
785
Jack Carterb4dbc172012-09-05 23:34:03 +0000786 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000787 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000788 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000789 struct ImmOp Imm;
790 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000791 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000792 };
793
794 SMLoc StartLoc, EndLoc;
795
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000796 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000797 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
798 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000799 const MCRegisterInfo *RegInfo,
800 SMLoc S, SMLoc E,
801 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000802 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000803 Op->RegIdx.Index = Index;
804 Op->RegIdx.RegInfo = RegInfo;
805 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000806 Op->RegIdx.Tok.Data = Str.data();
807 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000808 Op->StartLoc = S;
809 Op->EndLoc = E;
810 return Op;
811 }
812
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000813public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000814 /// Coerce the register to GPR32 and return the real register for the current
815 /// target.
816 unsigned getGPR32Reg() const {
817 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000818 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000819 unsigned ClassID = Mips::GPR32RegClassID;
820 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000821 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000822
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000823 /// Coerce the register to GPR32 and return the real register for the current
824 /// target.
825 unsigned getGPRMM16Reg() const {
826 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
827 unsigned ClassID = Mips::GPR32RegClassID;
828 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
829 }
830
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000831 /// Coerce the register to GPR64 and return the real register for the current
832 /// target.
833 unsigned getGPR64Reg() const {
834 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
835 unsigned ClassID = Mips::GPR64RegClassID;
836 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000837 }
838
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000839private:
840 /// Coerce the register to AFGR64 and return the real register for the current
841 /// target.
842 unsigned getAFGR64Reg() const {
843 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
844 if (RegIdx.Index % 2 != 0)
845 AsmParser.Warning(StartLoc, "Float register should be even.");
846 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
847 .getRegister(RegIdx.Index / 2);
848 }
849
850 /// Coerce the register to FGR64 and return the real register for the current
851 /// target.
852 unsigned getFGR64Reg() const {
853 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
854 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
855 .getRegister(RegIdx.Index);
856 }
857
858 /// Coerce the register to FGR32 and return the real register for the current
859 /// target.
860 unsigned getFGR32Reg() const {
861 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
862 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
863 .getRegister(RegIdx.Index);
864 }
865
866 /// Coerce the register to FGRH32 and return the real register for the current
867 /// target.
868 unsigned getFGRH32Reg() const {
869 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
870 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
871 .getRegister(RegIdx.Index);
872 }
873
874 /// Coerce the register to FCC and return the real register for the current
875 /// target.
876 unsigned getFCCReg() const {
877 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
878 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
879 .getRegister(RegIdx.Index);
880 }
881
882 /// Coerce the register to MSA128 and return the real register for the current
883 /// target.
884 unsigned getMSA128Reg() const {
885 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
886 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
887 // identical
888 unsigned ClassID = Mips::MSA128BRegClassID;
889 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
890 }
891
892 /// Coerce the register to MSACtrl and return the real register for the
893 /// current target.
894 unsigned getMSACtrlReg() const {
895 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
896 unsigned ClassID = Mips::MSACtrlRegClassID;
897 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
898 }
899
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000900 /// Coerce the register to COP0 and return the real register for the
901 /// current target.
902 unsigned getCOP0Reg() const {
903 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
904 unsigned ClassID = Mips::COP0RegClassID;
905 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
906 }
907
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000908 /// Coerce the register to COP2 and return the real register for the
909 /// current target.
910 unsigned getCOP2Reg() const {
911 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
912 unsigned ClassID = Mips::COP2RegClassID;
913 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
914 }
915
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000916 /// Coerce the register to COP3 and return the real register for the
917 /// current target.
918 unsigned getCOP3Reg() const {
919 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
920 unsigned ClassID = Mips::COP3RegClassID;
921 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
922 }
923
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000924 /// Coerce the register to ACC64DSP and return the real register for the
925 /// current target.
926 unsigned getACC64DSPReg() const {
927 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
928 unsigned ClassID = Mips::ACC64DSPRegClassID;
929 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
930 }
931
932 /// Coerce the register to HI32DSP and return the real register for the
933 /// current target.
934 unsigned getHI32DSPReg() const {
935 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
936 unsigned ClassID = Mips::HI32DSPRegClassID;
937 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
938 }
939
940 /// Coerce the register to LO32DSP and return the real register for the
941 /// current target.
942 unsigned getLO32DSPReg() const {
943 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
944 unsigned ClassID = Mips::LO32DSPRegClassID;
945 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
946 }
947
948 /// Coerce the register to CCR and return the real register for the
949 /// current target.
950 unsigned getCCRReg() const {
951 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
952 unsigned ClassID = Mips::CCRRegClassID;
953 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
954 }
955
956 /// Coerce the register to HWRegs and return the real register for the
957 /// current target.
958 unsigned getHWRegsReg() const {
959 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
960 unsigned ClassID = Mips::HWRegsRegClassID;
961 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
962 }
963
964public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000965 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000966 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000967 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000968 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000969 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000970 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000971 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000972 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000973 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000974
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000975 void addRegOperands(MCInst &Inst, unsigned N) const {
976 llvm_unreachable("Use a custom parser instead");
977 }
978
Daniel Sanders21bce302014-04-01 12:35:23 +0000979 /// Render the operand to an MCInst as a GPR32
980 /// Asserts if the wrong number of operands are requested, or the operand
981 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +0000982 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
983 assert(N == 1 && "Invalid number of operands!");
984 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
985 }
986
987 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
988 assert(N == 1 && "Invalid number of operands!");
989 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
990 }
991
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000992 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
993 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000994 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000995 }
996
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000997 void addGPRMM16AsmRegOperands(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(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001000 }
1001
Jozef Kolek1904fa22014-11-24 14:25:53 +00001002 void addGPRMM16AsmRegZeroOperands(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()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001005 }
1006
Zoran Jovanovic41688672015-02-10 16:36:20 +00001007 void addGPRMM16AsmRegMovePOperands(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()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001010 }
1011
Daniel Sanders21bce302014-04-01 12:35:23 +00001012 /// Render the operand to an MCInst as a GPR64
1013 /// Asserts if the wrong number of operands are requested, or the operand
1014 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001015 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1016 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001017 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001018 }
1019
1020 void addAFGR64AsmRegOperands(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(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001023 }
1024
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001025 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1026 assert(N == 1 && "Invalid number of operands!");
1027 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1028 }
1029
1030 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1031 assert(N == 1 && "Invalid number of operands!");
1032 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1033 }
1034
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001035 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1036 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001037 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001038 }
1039
1040 void addFGR32AsmRegOperands(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(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001043 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001044 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001045 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001046 AsmParser.getParser().printError(
1047 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1048 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001049 }
1050
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001051 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1052 assert(N == 1 && "Invalid number of operands!");
1053 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1054 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1055 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1056 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1057 "registers");
1058 }
1059
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001060 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1061 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001062 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001063 }
1064
1065 void addFCCAsmRegOperands(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(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001068 }
1069
1070 void addMSA128AsmRegOperands(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(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001073 }
1074
1075 void addMSACtrlAsmRegOperands(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(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001078 }
1079
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001080 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1081 assert(N == 1 && "Invalid number of operands!");
1082 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1083 }
1084
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001085 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1086 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001087 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001088 }
1089
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001090 void addCOP3AsmRegOperands(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(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001093 }
1094
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001095 void addACC64DSPAsmRegOperands(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(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001098 }
1099
1100 void addHI32DSPAsmRegOperands(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(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001103 }
1104
1105 void addLO32DSPAsmRegOperands(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(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 }
1109
1110 void addCCRAsmRegOperands(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(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001113 }
1114
1115 void addHWRegsAsmRegOperands(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(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001118 }
1119
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001120 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001121 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1122 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001123 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001124 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001125 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001126 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001127 Inst.addOperand(MCOperand::createImm(Imm));
1128 }
1129
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001130 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001131 void addSImmOperands(MCInst &Inst, unsigned N) const {
1132 if (isImm() && !isConstantImm()) {
1133 addExpr(Inst, getImm());
1134 return;
1135 }
1136 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1137 }
1138
1139 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001140 void addUImmOperands(MCInst &Inst, unsigned N) const {
1141 if (isImm() && !isConstantImm()) {
1142 addExpr(Inst, getImm());
1143 return;
1144 }
1145 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1146 }
1147
Daniel Sanders78e89022016-03-11 11:37:50 +00001148 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1149 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1150 assert(N == 1 && "Invalid number of operands!");
1151 int64_t Imm = getConstantImm() - Offset;
1152 Imm = SignExtend64<Bits>(Imm);
1153 Imm += Offset;
1154 Imm += AdjustOffset;
1155 Inst.addOperand(MCOperand::createImm(Imm));
1156 }
1157
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001158 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001159 assert(N == 1 && "Invalid number of operands!");
1160 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001161 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001162 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001163
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001164 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001165 assert(N == 2 && "Invalid number of operands!");
1166
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001167 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1168 ? getMemBase()->getGPR64Reg()
1169 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001170
1171 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001172 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001173 }
1174
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001175 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1176 assert(N == 2 && "Invalid number of operands!");
1177
Jim Grosbache9119e42015-05-13 18:37:00 +00001178 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001179
1180 const MCExpr *Expr = getMemOff();
1181 addExpr(Inst, Expr);
1182 }
1183
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001184 void addRegListOperands(MCInst &Inst, unsigned N) const {
1185 assert(N == 1 && "Invalid number of operands!");
1186
1187 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001188 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001189 }
1190
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001191 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1192 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001193 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001194 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001195 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1196 Inst.addOperand(MCOperand::createReg(
1197 RegIdx.RegInfo->getRegClass(
1198 AsmParser.getABI().AreGprs64bit()
1199 ? Mips::GPR64RegClassID
1200 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1201 Inst.addOperand(MCOperand::createReg(
1202 RegIdx.RegInfo->getRegClass(
1203 AsmParser.getABI().AreGprs64bit()
1204 ? Mips::GPR64RegClassID
1205 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001206 }
1207
Zoran Jovanovic41688672015-02-10 16:36:20 +00001208 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1209 assert(N == 2 && "Invalid number of operands!");
1210 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001211 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001212 }
1213
Craig Topper56c590a2014-04-29 07:58:02 +00001214 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001215 // As a special case until we sort out the definition of div/divu, accept
1216 // $0/$zero here so that MCK_ZERO works correctly.
1217 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001218 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001219
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001220 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001221 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001222
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001223 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001224 int64_t Res;
1225 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001226 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001227
Daniel Sanders52da7af2015-11-06 12:11:03 +00001228 bool isConstantImmz() const {
1229 return isConstantImm() && getConstantImm() == 0;
1230 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001231
Daniel Sandersea4f6532015-11-06 12:22:31 +00001232 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1233 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1234 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001235
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001236 template <unsigned Bits> bool isSImm() const {
1237 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1238 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001239
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001240 template <unsigned Bits> bool isUImm() const {
1241 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1242 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001243
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001244 template <unsigned Bits> bool isAnyImm() const {
1245 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1246 isUInt<Bits>(getConstantImm()))
1247 : isImm();
1248 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001249
Daniel Sanders78e89022016-03-11 11:37:50 +00001250 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1251 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001252 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001253
Hrvoje Varga46458d02016-02-25 12:53:29 +00001254 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1255 return isConstantImm() && getConstantImm() >= Bottom &&
1256 getConstantImm() <= Top;
1257 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001258
Craig Topper56c590a2014-04-29 07:58:02 +00001259 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001260 // Note: It's not possible to pretend that other operand kinds are tokens.
1261 // The matcher emitter checks tokens first.
1262 return Kind == k_Token;
1263 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001264
Craig Topper56c590a2014-04-29 07:58:02 +00001265 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001266
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001267 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001268 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001269 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001270
Simon Dardis4ccda502016-05-27 13:56:36 +00001271 // Allow relocation operators.
1272 // FIXME: This predicate and others need to look through binary expressions
1273 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001274 template <unsigned Bits, unsigned ShiftAmount = 0>
1275 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001276 if (!isMem())
1277 return false;
1278 if (!getMemBase()->isGPRAsmReg())
1279 return false;
1280 if (isa<MCTargetExpr>(getMemOff()) ||
1281 (isConstantMemOff() &&
1282 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1283 return true;
1284 MCValue Res;
1285 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1286 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001287 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001288
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001289 bool isMemWithGRPMM16Base() const {
1290 return isMem() && getMemBase()->isMM16AsmReg();
1291 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001292
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001293 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1294 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1295 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1296 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001297
Jozef Kolek12c69822014-12-23 16:16:33 +00001298 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1299 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1300 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1301 && (getMemBase()->getGPR32Reg() == Mips::SP);
1302 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001303
Daniel Sanderse473dc92016-05-09 13:38:25 +00001304 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1305 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1306 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1307 && (getMemBase()->getGPR32Reg() == Mips::GP);
1308 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001309
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001310 template <unsigned Bits, unsigned ShiftLeftAmount>
1311 bool isScaledUImm() const {
1312 return isConstantImm() &&
1313 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001314 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001315
Daniel Sanders97297772016-03-22 14:40:00 +00001316 template <unsigned Bits, unsigned ShiftLeftAmount>
1317 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001318 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1319 return true;
1320 // Operand can also be a symbol or symbol plus offset in case of relocations.
1321 if (Kind != k_Immediate)
1322 return false;
1323 MCValue Res;
1324 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1325 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001326 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001327
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001328 bool isRegList16() const {
1329 if (!isRegList())
1330 return false;
1331
1332 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001333 if (Size < 2 || Size > 5)
1334 return false;
1335
1336 unsigned R0 = RegList.List->front();
1337 unsigned R1 = RegList.List->back();
1338 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1339 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001340 return false;
1341
1342 int PrevReg = *RegList.List->begin();
1343 for (int i = 1; i < Size - 1; i++) {
1344 int Reg = (*(RegList.List))[i];
1345 if ( Reg != PrevReg + 1)
1346 return false;
1347 PrevReg = Reg;
1348 }
1349
1350 return true;
1351 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001352
Vladimir Medic2b953d02013-10-01 09:48:56 +00001353 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001354
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001355 bool isLSAImm() const {
1356 if (!isConstantImm())
1357 return false;
1358 int64_t Val = getConstantImm();
1359 return 1 <= Val && Val <= 4;
1360 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001361
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001362 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001363
Zoran Jovanovic41688672015-02-10 16:36:20 +00001364 bool isMovePRegPair() const {
1365 if (Kind != k_RegList || RegList.List->size() != 2)
1366 return false;
1367
1368 unsigned R0 = RegList.List->front();
1369 unsigned R1 = RegList.List->back();
1370
1371 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1372 (R0 == Mips::A1 && R1 == Mips::A3) ||
1373 (R0 == Mips::A2 && R1 == Mips::A3) ||
1374 (R0 == Mips::A0 && R1 == Mips::S5) ||
1375 (R0 == Mips::A0 && R1 == Mips::S6) ||
1376 (R0 == Mips::A0 && R1 == Mips::A1) ||
1377 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001378 (R0 == Mips::A0 && R1 == Mips::A3) ||
1379 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1380 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1381 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1382 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1383 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1384 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1385 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1386 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001387 return true;
1388
1389 return false;
1390 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001391
1392 StringRef getToken() const {
1393 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001394 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001395 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001396
Zlatko Buljanba553a62016-05-09 08:07:28 +00001397 bool isRegPair() const {
1398 return Kind == k_RegPair && RegIdx.Index <= 30;
1399 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001400
Craig Topper56c590a2014-04-29 07:58:02 +00001401 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001402 // As a special case until we sort out the definition of div/divu, accept
1403 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001404 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1405 RegIdx.Kind & RegKind_GPR)
1406 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001407
Daniel Sanders976d9382016-07-05 13:38:40 +00001408 llvm_unreachable("Invalid access!");
1409 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001410 }
1411
Jack Carterb4dbc172012-09-05 23:34:03 +00001412 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001413 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001414 return Imm.Val;
1415 }
1416
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001417 int64_t getConstantImm() const {
1418 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001419 int64_t Value = 0;
1420 (void)Val->evaluateAsAbsolute(Value);
1421 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001422 }
1423
1424 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001425 assert((Kind == k_Memory) && "Invalid access!");
1426 return Mem.Base;
1427 }
1428
1429 const MCExpr *getMemOff() const {
1430 assert((Kind == k_Memory) && "Invalid access!");
1431 return Mem.Off;
1432 }
1433
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001434 int64_t getConstantMemOff() const {
1435 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1436 }
1437
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001438 const SmallVectorImpl<unsigned> &getRegList() const {
1439 assert((Kind == k_RegList) && "Invalid access!");
1440 return *(RegList.List);
1441 }
1442
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001443 unsigned getRegPair() const {
1444 assert((Kind == k_RegPair) && "Invalid access!");
1445 return RegIdx.Index;
1446 }
1447
David Blaikie960ea3f2014-06-08 16:18:35 +00001448 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1449 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001450 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001451 Op->Tok.Data = Str.data();
1452 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001453 Op->StartLoc = S;
1454 Op->EndLoc = S;
1455 return Op;
1456 }
1457
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001458 /// Create a numeric register (e.g. $1). The exact register remains
1459 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001460 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001461 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1462 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001463 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001464 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001465 }
1466
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001467 /// Create a register that is definitely a GPR.
1468 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001469 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001470 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1471 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1472 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001473 }
1474
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001475 /// Create a register that is definitely a FGR.
1476 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001477 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001478 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1479 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1480 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001481 }
1482
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001483 /// Create a register that is definitely a HWReg.
1484 /// This is typically only used for named registers such as $hwr_cpunum.
1485 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001486 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001487 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001488 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001489 }
1490
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001491 /// Create a register that is definitely an FCC.
1492 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001493 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001494 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1495 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1496 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001497 }
1498
1499 /// Create a register that is definitely an ACC.
1500 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001501 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001502 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1503 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1504 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001505 }
1506
1507 /// Create a register that is definitely an MSA128.
1508 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001509 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001510 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1511 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1512 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001513 }
1514
1515 /// Create a register that is definitely an MSACtrl.
1516 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001517 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001518 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1519 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1520 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001521 }
1522
David Blaikie960ea3f2014-06-08 16:18:35 +00001523 static std::unique_ptr<MipsOperand>
1524 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001525 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001526 Op->Imm.Val = Val;
1527 Op->StartLoc = S;
1528 Op->EndLoc = E;
1529 return Op;
1530 }
1531
David Blaikie960ea3f2014-06-08 16:18:35 +00001532 static std::unique_ptr<MipsOperand>
1533 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1534 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001535 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001536 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001537 Op->Mem.Off = Off;
1538 Op->StartLoc = S;
1539 Op->EndLoc = E;
1540 return Op;
1541 }
1542
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001543 static std::unique_ptr<MipsOperand>
1544 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1545 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001546 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001547
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001548 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001549 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001550 Op->StartLoc = StartLoc;
1551 Op->EndLoc = EndLoc;
1552 return Op;
1553 }
1554
Daniel Sandersd044e492016-05-09 13:10:57 +00001555 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1556 SMLoc S, SMLoc E,
1557 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001558 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001559 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001560 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1561 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001562 Op->StartLoc = S;
1563 Op->EndLoc = E;
1564 return Op;
1565 }
1566
Simon Dardis509da1a2017-02-13 16:06:48 +00001567 bool isGPRZeroAsmReg() const {
1568 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1569 }
1570
1571 bool isGPRNonZeroAsmReg() const {
1572 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1573 RegIdx.Index <= 31;
1574 }
1575
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001576 bool isGPRAsmReg() const {
1577 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001578 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001579
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001580 bool isMM16AsmReg() const {
1581 if (!(isRegIdx() && RegIdx.Kind))
1582 return false;
1583 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1584 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001585
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001586 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001587 bool isMM16AsmRegZero() const {
1588 if (!(isRegIdx() && RegIdx.Kind))
1589 return false;
1590 return (RegIdx.Index == 0 ||
1591 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1592 RegIdx.Index == 17);
1593 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001594
Zoran Jovanovic41688672015-02-10 16:36:20 +00001595 bool isMM16AsmRegMoveP() const {
1596 if (!(isRegIdx() && RegIdx.Kind))
1597 return false;
1598 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1599 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1600 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001601
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001602 bool isFGRAsmReg() const {
1603 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1604 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001605 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001606
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001607 bool isStrictlyFGRAsmReg() const {
1608 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1609 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1610 }
1611
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001612 bool isHWRegsAsmReg() const {
1613 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001614 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001615
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001616 bool isCCRAsmReg() const {
1617 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001618 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001619
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001620 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001621 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1622 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001623 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001624 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001625
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001626 bool isACCAsmReg() const {
1627 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001628 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001629
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001630 bool isCOP0AsmReg() const {
1631 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1632 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001633
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001634 bool isCOP2AsmReg() const {
1635 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001636 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001637
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001638 bool isCOP3AsmReg() const {
1639 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1640 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001641
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001642 bool isMSA128AsmReg() const {
1643 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001644 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001645
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001646 bool isMSACtrlAsmReg() const {
1647 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001648 }
1649
Jack Carterb4dbc172012-09-05 23:34:03 +00001650 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001651 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001652 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001653 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001654
Craig Topper56c590a2014-04-29 07:58:02 +00001655 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001656 switch (Kind) {
1657 case k_Immediate:
1658 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001659 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001660 OS << ">";
1661 break;
1662 case k_Memory:
1663 OS << "Mem<";
1664 Mem.Base->print(OS);
1665 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001666 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001667 OS << ">";
1668 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001669 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001670 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1671 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001672 break;
1673 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001674 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001675 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001676 case k_RegList:
1677 OS << "RegList< ";
1678 for (auto Reg : (*RegList.List))
1679 OS << Reg << " ";
1680 OS << ">";
1681 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001682 case k_RegPair:
1683 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1684 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001685 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001686 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001687
1688 bool isValidForTie(const MipsOperand &Other) const {
1689 if (Kind != Other.Kind)
1690 return false;
1691
1692 switch (Kind) {
1693 default:
1694 llvm_unreachable("Unexpected kind");
1695 return false;
1696 case k_RegisterIndex: {
1697 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1698 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1699 return Token == OtherToken;
1700 }
1701 }
1702 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001703}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001704
1705} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001706
Jack Carter9e65aa32013-03-22 00:05:30 +00001707namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001708
Jack Carter9e65aa32013-03-22 00:05:30 +00001709extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001710
1711} // end namespace llvm
1712
Jack Carter9e65aa32013-03-22 00:05:30 +00001713static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1714 return MipsInsts[Opcode];
1715}
1716
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001717static bool hasShortDelaySlot(unsigned Opcode) {
1718 switch (Opcode) {
1719 case Mips::JALS_MM:
1720 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001721 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001722 case Mips::BGEZALS_MM:
1723 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001724 return true;
1725 default:
1726 return false;
1727 }
1728}
1729
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001730static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1731 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1732 return &SRExpr->getSymbol();
1733 }
1734
1735 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1736 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1737 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1738
1739 if (LHSSym)
1740 return LHSSym;
1741
1742 if (RHSSym)
1743 return RHSSym;
1744
1745 return nullptr;
1746 }
1747
1748 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1749 return getSingleMCSymbol(UExpr->getSubExpr());
1750
1751 return nullptr;
1752}
1753
1754static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1755 if (isa<MCSymbolRefExpr>(Expr))
1756 return 1;
1757
1758 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1759 return countMCSymbolRefExpr(BExpr->getLHS()) +
1760 countMCSymbolRefExpr(BExpr->getRHS());
1761
1762 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1763 return countMCSymbolRefExpr(UExpr->getSubExpr());
1764
1765 return 0;
1766}
1767
Jack Carter9e65aa32013-03-22 00:05:30 +00001768bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001769 MCStreamer &Out,
1770 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001771 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001772 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001773 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001774
Jack Carter9e65aa32013-03-22 00:05:30 +00001775 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001776
1777 if (MCID.isBranch() || MCID.isCall()) {
1778 const unsigned Opcode = Inst.getOpcode();
1779 MCOperand Offset;
1780
1781 switch (Opcode) {
1782 default:
1783 break;
Kai Nackee0245392015-01-27 19:11:28 +00001784 case Mips::BBIT0:
1785 case Mips::BBIT032:
1786 case Mips::BBIT1:
1787 case Mips::BBIT132:
1788 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001789 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001790
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001791 case Mips::BEQ:
1792 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001793 case Mips::BEQ_MM:
1794 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001795 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001796 Offset = Inst.getOperand(2);
1797 if (!Offset.isImm())
1798 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001799 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001800 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001801 if (OffsetToAlignment(Offset.getImm(),
1802 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001803 return Error(IDLoc, "branch to misaligned address");
1804 break;
1805 case Mips::BGEZ:
1806 case Mips::BGTZ:
1807 case Mips::BLEZ:
1808 case Mips::BLTZ:
1809 case Mips::BGEZAL:
1810 case Mips::BLTZAL:
1811 case Mips::BC1F:
1812 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001813 case Mips::BGEZ_MM:
1814 case Mips::BGTZ_MM:
1815 case Mips::BLEZ_MM:
1816 case Mips::BLTZ_MM:
1817 case Mips::BGEZAL_MM:
1818 case Mips::BLTZAL_MM:
1819 case Mips::BC1F_MM:
1820 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001821 case Mips::BC1EQZC_MMR6:
1822 case Mips::BC1NEZC_MMR6:
1823 case Mips::BC2EQZC_MMR6:
1824 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001825 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001826 Offset = Inst.getOperand(1);
1827 if (!Offset.isImm())
1828 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001829 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001830 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001831 if (OffsetToAlignment(Offset.getImm(),
1832 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001833 return Error(IDLoc, "branch to misaligned address");
1834 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001835 case Mips::BGEC: case Mips::BGEC_MMR6:
1836 case Mips::BLTC: case Mips::BLTC_MMR6:
1837 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1838 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1839 case Mips::BEQC: case Mips::BEQC_MMR6:
1840 case Mips::BNEC: case Mips::BNEC_MMR6:
1841 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1842 Offset = Inst.getOperand(2);
1843 if (!Offset.isImm())
1844 break; // We'll deal with this situation later on when applying fixups.
1845 if (!isIntN(18, Offset.getImm()))
1846 return Error(IDLoc, "branch target out of range");
1847 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1848 return Error(IDLoc, "branch to misaligned address");
1849 break;
1850 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1851 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1852 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1853 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1854 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1855 Offset = Inst.getOperand(1);
1856 if (!Offset.isImm())
1857 break; // We'll deal with this situation later on when applying fixups.
1858 if (!isIntN(18, Offset.getImm()))
1859 return Error(IDLoc, "branch target out of range");
1860 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1861 return Error(IDLoc, "branch to misaligned address");
1862 break;
1863 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1864 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1865 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1866 Offset = Inst.getOperand(1);
1867 if (!Offset.isImm())
1868 break; // We'll deal with this situation later on when applying fixups.
1869 if (!isIntN(23, Offset.getImm()))
1870 return Error(IDLoc, "branch target out of range");
1871 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1872 return Error(IDLoc, "branch to misaligned address");
1873 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001874 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001875 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001876 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001877 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001878 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1879 Offset = Inst.getOperand(1);
1880 if (!Offset.isImm())
1881 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001882 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001883 return Error(IDLoc, "branch target out of range");
1884 if (OffsetToAlignment(Offset.getImm(), 2LL))
1885 return Error(IDLoc, "branch to misaligned address");
1886 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001887 }
1888 }
1889
Daniel Sandersa84989a2014-06-16 13:25:35 +00001890 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1891 // We still accept it but it is a normal nop.
1892 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1893 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1894 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1895 "nop instruction");
1896 }
1897
Kai Nackee0245392015-01-27 19:11:28 +00001898 if (hasCnMips()) {
1899 const unsigned Opcode = Inst.getOpcode();
1900 MCOperand Opnd;
1901 int Imm;
1902
1903 switch (Opcode) {
1904 default:
1905 break;
1906
1907 case Mips::BBIT0:
1908 case Mips::BBIT032:
1909 case Mips::BBIT1:
1910 case Mips::BBIT132:
1911 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1912 // The offset is handled above
1913 Opnd = Inst.getOperand(1);
1914 if (!Opnd.isImm())
1915 return Error(IDLoc, "expected immediate operand kind");
1916 Imm = Opnd.getImm();
1917 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1918 Opcode == Mips::BBIT1 ? 63 : 31))
1919 return Error(IDLoc, "immediate operand value out of range");
1920 if (Imm > 31) {
1921 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1922 : Mips::BBIT132);
1923 Inst.getOperand(1).setImm(Imm - 32);
1924 }
1925 break;
1926
Kai Nackee0245392015-01-27 19:11:28 +00001927 case Mips::SEQi:
1928 case Mips::SNEi:
1929 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1930 Opnd = Inst.getOperand(2);
1931 if (!Opnd.isImm())
1932 return Error(IDLoc, "expected immediate operand kind");
1933 Imm = Opnd.getImm();
1934 if (!isInt<10>(Imm))
1935 return Error(IDLoc, "immediate operand value out of range");
1936 break;
1937 }
1938 }
1939
Simon Dardis509da1a2017-02-13 16:06:48 +00001940 // Warn on division by zero. We're checking here as all instructions get
1941 // processed here, not just the macros that need expansion.
1942 //
1943 // The MIPS backend models most of the divison instructions and macros as
1944 // three operand instructions. The pre-R6 divide instructions however have
1945 // two operands and explicitly define HI/LO as part of the instruction,
1946 // not in the operands.
1947 unsigned FirstOp = 1;
1948 unsigned SecondOp = 2;
1949 switch (Inst.getOpcode()) {
1950 default:
1951 break;
1952 case Mips::SDivIMacro:
1953 case Mips::UDivIMacro:
1954 case Mips::DSDivIMacro:
1955 case Mips::DUDivIMacro:
1956 if (Inst.getOperand(2).getImm() == 0) {
1957 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1958 Inst.getOperand(1).getReg() == Mips::ZERO_64)
1959 Warning(IDLoc, "dividing zero by zero");
1960 else
1961 Warning(IDLoc, "division by zero");
1962 }
1963 break;
1964 case Mips::DSDIV:
1965 case Mips::SDIV:
1966 case Mips::UDIV:
1967 case Mips::DUDIV:
1968 case Mips::UDIV_MM:
1969 case Mips::SDIV_MM:
1970 FirstOp = 0;
1971 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00001972 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00001973 case Mips::SDivMacro:
1974 case Mips::DSDivMacro:
1975 case Mips::UDivMacro:
1976 case Mips::DUDivMacro:
1977 case Mips::DIV:
1978 case Mips::DIVU:
1979 case Mips::DDIV:
1980 case Mips::DDIVU:
1981 case Mips::DIVU_MMR6:
1982 case Mips::DDIVU_MM64R6:
1983 case Mips::DIV_MMR6:
1984 case Mips::DDIV_MM64R6:
1985 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
1986 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
1987 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
1988 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
1989 Warning(IDLoc, "dividing zero by zero");
1990 else
1991 Warning(IDLoc, "division by zero");
1992 }
1993 break;
1994 }
1995
Simon Atanasyan50485142016-12-12 17:40:26 +00001996 // For PIC code convert unconditional jump to unconditional branch.
1997 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
1998 inPicMode()) {
1999 MCInst BInst;
2000 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
2001 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2002 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2003 BInst.addOperand(Inst.getOperand(0));
2004 Inst = BInst;
2005 }
2006
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002007 // This expansion is not in a function called by tryExpandInstruction()
2008 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002009 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2010 inPicMode()) {
2011 warnIfNoMacro(IDLoc);
2012
2013 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2014
2015 // We can do this expansion if there's only 1 symbol in the argument
2016 // expression.
2017 if (countMCSymbolRefExpr(JalExpr) > 1)
2018 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2019
2020 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002021 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002022 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2023
2024 // FIXME: Add support for label+offset operands (currently causes an error).
2025 // FIXME: Add support for forward-declared local symbols.
2026 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002027 if (JalSym->isInSection() || JalSym->isTemporary() ||
2028 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002029 if (isABI_O32()) {
2030 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002031 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002032 // R_(MICRO)MIPS_GOT16 label
2033 // addiu $25, $25, 0
2034 // R_(MICRO)MIPS_LO16 label
2035 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002036 const MCExpr *Got16RelocExpr =
2037 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2038 const MCExpr *Lo16RelocExpr =
2039 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002040
Daniel Sandersa736b372016-04-29 13:33:12 +00002041 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2042 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2043 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2044 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002045 } else if (isABI_N32() || isABI_N64()) {
2046 // If it's a local symbol and the N32/N64 ABIs are being used,
2047 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002048 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002049 // R_(MICRO)MIPS_GOT_DISP label
2050 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002051 const MCExpr *GotDispRelocExpr =
2052 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002053
Daniel Sandersa736b372016-04-29 13:33:12 +00002054 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2055 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2056 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002057 }
2058 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002059 // If it's an external/weak symbol, we expand to:
2060 // lw/ld $25, 0($gp)
2061 // R_(MICRO)MIPS_CALL16 label
2062 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002063 const MCExpr *Call16RelocExpr =
2064 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002065
Daniel Sandersa736b372016-04-29 13:33:12 +00002066 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2067 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002068 }
2069
2070 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002071 if (IsCpRestoreSet && inMicroMipsMode())
2072 JalrInst.setOpcode(Mips::JALRS_MM);
2073 else
2074 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002075 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2076 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2077
2078 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2079 // This relocation is supposed to be an optimization hint for the linker
2080 // and is not necessary for correctness.
2081
2082 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002083 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002084 }
2085
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002086 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2087 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002088 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002089 // reference or immediate we may have to expand instructions.
2090 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002091 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002092 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2093 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002094 MCOperand &Op = Inst.getOperand(i);
2095 if (Op.isImm()) {
2096 int MemOffset = Op.getImm();
2097 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002098 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002099 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00002100 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002101 }
2102 } else if (Op.isExpr()) {
2103 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002104 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002105 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002106 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002107 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002108 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002109 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002110 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002111 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002112 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002113 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002114 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002115 }
2116 }
2117 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002118 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002119 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002120
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002121 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002122 if (MCID.mayLoad()) {
2123 // Try to create 16-bit GP relative load instruction.
2124 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2125 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2126 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2127 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2128 MCOperand &Op = Inst.getOperand(i);
2129 if (Op.isImm()) {
2130 int MemOffset = Op.getImm();
2131 MCOperand &DstReg = Inst.getOperand(0);
2132 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002133 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002134 getContext().getRegisterInfo()->getRegClass(
2135 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002136 (BaseReg.getReg() == Mips::GP ||
2137 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002138
Daniel Sandersa736b372016-04-29 13:33:12 +00002139 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2140 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002141 return false;
2142 }
2143 }
2144 }
2145 } // for
2146 } // if load
2147
2148 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2149
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002150 MCOperand Opnd;
2151 int Imm;
2152
2153 switch (Inst.getOpcode()) {
2154 default:
2155 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002156 case Mips::ADDIUSP_MM:
2157 Opnd = Inst.getOperand(0);
2158 if (!Opnd.isImm())
2159 return Error(IDLoc, "expected immediate operand kind");
2160 Imm = Opnd.getImm();
2161 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2162 Imm % 4 != 0)
2163 return Error(IDLoc, "immediate operand value out of range");
2164 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002165 case Mips::SLL16_MM:
2166 case Mips::SRL16_MM:
2167 Opnd = Inst.getOperand(2);
2168 if (!Opnd.isImm())
2169 return Error(IDLoc, "expected immediate operand kind");
2170 Imm = Opnd.getImm();
2171 if (Imm < 1 || Imm > 8)
2172 return Error(IDLoc, "immediate operand value out of range");
2173 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002174 case Mips::LI16_MM:
2175 Opnd = Inst.getOperand(1);
2176 if (!Opnd.isImm())
2177 return Error(IDLoc, "expected immediate operand kind");
2178 Imm = Opnd.getImm();
2179 if (Imm < -1 || Imm > 126)
2180 return Error(IDLoc, "immediate operand value out of range");
2181 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002182 case Mips::ADDIUR2_MM:
2183 Opnd = Inst.getOperand(2);
2184 if (!Opnd.isImm())
2185 return Error(IDLoc, "expected immediate operand kind");
2186 Imm = Opnd.getImm();
2187 if (!(Imm == 1 || Imm == -1 ||
2188 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2189 return Error(IDLoc, "immediate operand value out of range");
2190 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002191 case Mips::ANDI16_MM:
2192 Opnd = Inst.getOperand(2);
2193 if (!Opnd.isImm())
2194 return Error(IDLoc, "expected immediate operand kind");
2195 Imm = Opnd.getImm();
2196 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2197 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2198 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2199 return Error(IDLoc, "immediate operand value out of range");
2200 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002201 case Mips::LBU16_MM:
2202 Opnd = Inst.getOperand(2);
2203 if (!Opnd.isImm())
2204 return Error(IDLoc, "expected immediate operand kind");
2205 Imm = Opnd.getImm();
2206 if (Imm < -1 || Imm > 14)
2207 return Error(IDLoc, "immediate operand value out of range");
2208 break;
2209 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002210 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002211 Opnd = Inst.getOperand(2);
2212 if (!Opnd.isImm())
2213 return Error(IDLoc, "expected immediate operand kind");
2214 Imm = Opnd.getImm();
2215 if (Imm < 0 || Imm > 15)
2216 return Error(IDLoc, "immediate operand value out of range");
2217 break;
2218 case Mips::LHU16_MM:
2219 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002220 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002221 Opnd = Inst.getOperand(2);
2222 if (!Opnd.isImm())
2223 return Error(IDLoc, "expected immediate operand kind");
2224 Imm = Opnd.getImm();
2225 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2226 return Error(IDLoc, "immediate operand value out of range");
2227 break;
2228 case Mips::LW16_MM:
2229 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002230 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002231 Opnd = Inst.getOperand(2);
2232 if (!Opnd.isImm())
2233 return Error(IDLoc, "expected immediate operand kind");
2234 Imm = Opnd.getImm();
2235 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2236 return Error(IDLoc, "immediate operand value out of range");
2237 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002238 case Mips::ADDIUPC_MM:
2239 MCOperand Opnd = Inst.getOperand(1);
2240 if (!Opnd.isImm())
2241 return Error(IDLoc, "expected immediate operand kind");
2242 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002243 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002244 return Error(IDLoc, "immediate operand value out of range");
2245 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002246 }
2247 }
2248
Daniel Sandersd8c07762016-04-18 12:35:36 +00002249 bool FillDelaySlot =
2250 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2251 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002252 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002253
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002254 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002255 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002256 switch (ExpandResult) {
2257 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002258 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002259 break;
2260 case MER_Success:
2261 break;
2262 case MER_Fail:
2263 return true;
2264 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002265
Daniel Sanderscda908a2016-05-16 09:10:13 +00002266 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2267 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2268 if (inMicroMipsMode())
2269 TOut.setUsesMicroMips();
2270
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002271 // If this instruction has a delay slot and .set reorder is active,
2272 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002273 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002274 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2275 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002276 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002277
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002278 if ((Inst.getOpcode() == Mips::JalOneReg ||
2279 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2280 isPicAndNotNxxAbi()) {
2281 if (IsCpRestoreSet) {
2282 // We need a NOP between the JALR and the LW:
2283 // If .set reorder has been used, we've already emitted a NOP.
2284 // If .set noreorder has been used, we need to emit a NOP at this point.
2285 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002286 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2287 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002288
2289 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002290 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002291 } else
2292 Warning(IDLoc, "no .cprestore used in PIC mode");
2293 }
2294
Jack Carter9e65aa32013-03-22 00:05:30 +00002295 return false;
2296}
2297
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002298MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002299MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2300 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002301 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002302 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002303 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002304 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002305 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002306 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002307 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002308 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002309 case Mips::LoadAddrImm64:
2310 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2311 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2312 "expected immediate operand kind");
2313
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002314 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2315 Inst.getOperand(1),
2316 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002317 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002318 ? MER_Fail
2319 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002320 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002321 case Mips::LoadAddrReg64:
2322 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2323 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2324 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2325 "expected immediate operand kind");
2326
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002327 return expandLoadAddress(Inst.getOperand(0).getReg(),
2328 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2329 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002330 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002331 ? MER_Fail
2332 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002333 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002334 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002335 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2336 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002337 case Mips::SWM_MM:
2338 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002339 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2340 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002341 case Mips::JalOneReg:
2342 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002343 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002344 case Mips::BneImm:
2345 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002346 case Mips::BEQLImmMacro:
2347 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002348 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002349 case Mips::BLT:
2350 case Mips::BLE:
2351 case Mips::BGE:
2352 case Mips::BGT:
2353 case Mips::BLTU:
2354 case Mips::BLEU:
2355 case Mips::BGEU:
2356 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002357 case Mips::BLTL:
2358 case Mips::BLEL:
2359 case Mips::BGEL:
2360 case Mips::BGTL:
2361 case Mips::BLTUL:
2362 case Mips::BLEUL:
2363 case Mips::BGEUL:
2364 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002365 case Mips::BLTImmMacro:
2366 case Mips::BLEImmMacro:
2367 case Mips::BGEImmMacro:
2368 case Mips::BGTImmMacro:
2369 case Mips::BLTUImmMacro:
2370 case Mips::BLEUImmMacro:
2371 case Mips::BGEUImmMacro:
2372 case Mips::BGTUImmMacro:
2373 case Mips::BLTLImmMacro:
2374 case Mips::BLELImmMacro:
2375 case Mips::BGELImmMacro:
2376 case Mips::BGTLImmMacro:
2377 case Mips::BLTULImmMacro:
2378 case Mips::BLEULImmMacro:
2379 case Mips::BGEULImmMacro:
2380 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002381 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002382 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002383 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002384 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2385 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002386 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002387 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002388 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2389 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002390 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002391 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002392 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2393 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002394 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002395 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002396 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2397 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002398 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002399 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2400 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002401 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002402 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002403 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002404 case Mips::PseudoTRUNC_W_D:
2405 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2406 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002407
2408 case Mips::LoadImmSingleGPR:
2409 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2410 ? MER_Fail
2411 : MER_Success;
2412 case Mips::LoadImmSingleFGR:
2413 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2414 ? MER_Fail
2415 : MER_Success;
2416 case Mips::LoadImmDoubleGPR:
2417 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2418 ? MER_Fail
2419 : MER_Success;
2420 case Mips::LoadImmDoubleFGR:
2421 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2422 ? MER_Fail
2423 : MER_Success;
2424 case Mips::LoadImmDoubleFGR_32:
2425 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2426 ? MER_Fail
2427 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002428 case Mips::Ulh:
2429 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2430 case Mips::Ulhu:
2431 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002432 case Mips::Ush:
2433 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002434 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002435 case Mips::Usw:
2436 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002437 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002438 case Mips::NORImm64:
2439 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2440 case Mips::SLTImm64:
2441 if (isInt<16>(Inst.getOperand(2).getImm())) {
2442 Inst.setOpcode(Mips::SLTi64);
2443 return MER_NotAMacro;
2444 }
2445 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2446 case Mips::SLTUImm64:
2447 if (isInt<16>(Inst.getOperand(2).getImm())) {
2448 Inst.setOpcode(Mips::SLTiu64);
2449 return MER_NotAMacro;
2450 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002451 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002452 case Mips::ADDi: case Mips::ADDi_MM:
2453 case Mips::ADDiu: case Mips::ADDiu_MM:
2454 case Mips::SLTi: case Mips::SLTi_MM:
2455 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002456 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2457 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2458 int64_t ImmValue = Inst.getOperand(2).getImm();
2459 if (isInt<16>(ImmValue))
2460 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002461 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2462 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002463 }
2464 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002465 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2466 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2467 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002468 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2469 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2470 int64_t ImmValue = Inst.getOperand(2).getImm();
2471 if (isUInt<16>(ImmValue))
2472 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002473 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2474 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002475 }
2476 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002477 case Mips::ROL:
2478 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002479 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002480 case Mips::ROLImm:
2481 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002482 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002483 case Mips::DROL:
2484 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002485 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002486 case Mips::DROLImm:
2487 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002488 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002489 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002490 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002491 case Mips::MULImmMacro:
2492 case Mips::DMULImmMacro:
2493 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2494 case Mips::MULOMacro:
2495 case Mips::DMULOMacro:
2496 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2497 case Mips::MULOUMacro:
2498 case Mips::DMULOUMacro:
2499 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2500 case Mips::DMULMacro:
2501 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002502 case Mips::LDMacro:
2503 case Mips::SDMacro:
2504 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2505 Inst.getOpcode() == Mips::LDMacro)
2506 ? MER_Fail
2507 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002508 case Mips::SEQMacro:
2509 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2510 case Mips::SEQIMacro:
2511 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002512 }
Jack Carter30a59822012-10-04 04:03:53 +00002513}
Jack Carter92995f12012-10-06 00:53:28 +00002514
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002515bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002516 MCStreamer &Out,
2517 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002518 MipsTargetStreamer &TOut = getTargetStreamer();
2519
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002520 // Create a JALR instruction which is going to replace the pseudo-JAL.
2521 MCInst JalrInst;
2522 JalrInst.setLoc(IDLoc);
2523 const MCOperand FirstRegOp = Inst.getOperand(0);
2524 const unsigned Opcode = Inst.getOpcode();
2525
2526 if (Opcode == Mips::JalOneReg) {
2527 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002528 if (IsCpRestoreSet && inMicroMipsMode()) {
2529 JalrInst.setOpcode(Mips::JALRS16_MM);
2530 JalrInst.addOperand(FirstRegOp);
2531 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002532 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002533 JalrInst.addOperand(FirstRegOp);
2534 } else {
2535 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002536 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002537 JalrInst.addOperand(FirstRegOp);
2538 }
2539 } else if (Opcode == Mips::JalTwoReg) {
2540 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002541 if (IsCpRestoreSet && inMicroMipsMode())
2542 JalrInst.setOpcode(Mips::JALRS_MM);
2543 else
2544 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002545 JalrInst.addOperand(FirstRegOp);
2546 const MCOperand SecondRegOp = Inst.getOperand(1);
2547 JalrInst.addOperand(SecondRegOp);
2548 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002549 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002550
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002551 // If .set reorder is active and branch instruction has a delay slot,
2552 // emit a NOP after it.
2553 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002554 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2555 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2556 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002557
2558 return false;
2559}
2560
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002561/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002562template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002563 unsigned BitNum = findFirstSet(x);
2564
2565 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2566}
2567
2568/// Load (or add) an immediate into a register.
2569///
2570/// @param ImmValue The immediate to load.
2571/// @param DstReg The register that will hold the immediate.
2572/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2573/// for a simple initialization.
2574/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2575/// @param IsAddress True if the immediate represents an address. False if it
2576/// is an integer.
2577/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002578bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002579 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002580 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2581 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002582 MipsTargetStreamer &TOut = getTargetStreamer();
2583
Toma Tabacu00e98672015-05-01 12:19:27 +00002584 if (!Is32BitImm && !isGP64bit()) {
2585 Error(IDLoc, "instruction requires a 64-bit architecture");
2586 return true;
2587 }
2588
Daniel Sanders03f9c012015-07-14 12:24:22 +00002589 if (Is32BitImm) {
2590 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2591 // Sign extend up to 64-bit so that the predicates match the hardware
2592 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2593 // true.
2594 ImmValue = SignExtend64<32>(ImmValue);
2595 } else {
2596 Error(IDLoc, "instruction requires a 32-bit immediate");
2597 return true;
2598 }
2599 }
2600
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002601 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2602 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2603
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002604 bool UseSrcReg = false;
2605 if (SrcReg != Mips::NoRegister)
2606 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002607
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002608 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002609 if (UseSrcReg &&
2610 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002611 // At this point we need AT to perform the expansions and we exit if it is
2612 // not available.
2613 unsigned ATReg = getATReg(IDLoc);
2614 if (!ATReg)
2615 return true;
2616 TmpReg = ATReg;
2617 }
2618
Daniel Sanders03f9c012015-07-14 12:24:22 +00002619 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002620 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002621 SrcReg = ZeroReg;
2622
2623 // This doesn't quite follow the usual ABI expectations for N32 but matches
2624 // traditional assembler behaviour. N32 would normally use addiu for both
2625 // integers and addresses.
2626 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002627 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002628 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002629 }
2630
Daniel Sandersa736b372016-04-29 13:33:12 +00002631 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002632 return false;
2633 }
2634
2635 if (isUInt<16>(ImmValue)) {
2636 unsigned TmpReg = DstReg;
2637 if (SrcReg == DstReg) {
2638 TmpReg = getATReg(IDLoc);
2639 if (!TmpReg)
2640 return true;
2641 }
2642
Daniel Sandersa736b372016-04-29 13:33:12 +00002643 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002644 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002645 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002646 return false;
2647 }
2648
2649 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002650 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002651
Toma Tabacu79588102015-04-29 10:19:56 +00002652 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2653 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002654 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002655 // Traditional behaviour seems to special case this particular value. It's
2656 // not clear why other masks are handled differently.
2657 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002658 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2659 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002660 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002661 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002662 return false;
2663 }
2664
2665 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002666 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002667 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2668 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002669 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002670 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002671 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002672 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002673 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002674 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002675
Daniel Sandersa736b372016-04-29 13:33:12 +00002676 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002677 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002678 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002679 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002680 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002681 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002682 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002683
2684 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2685 if (Is32BitImm) {
2686 Error(IDLoc, "instruction requires a 32-bit immediate");
2687 return true;
2688 }
2689
2690 // Traditionally, these immediates are shifted as little as possible and as
2691 // such we align the most significant bit to bit 15 of our temporary.
2692 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2693 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2694 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2695 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002696 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2697 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002698
2699 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002700 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002701
2702 return false;
2703 }
2704
2705 warnIfNoMacro(IDLoc);
2706
2707 // The remaining case is packed with a sequence of dsll and ori with zeros
2708 // being omitted and any neighbouring dsll's being coalesced.
2709 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2710
2711 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2712 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002713 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002714 return false;
2715
2716 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2717 // skip it and defer the shift to the next chunk.
2718 unsigned ShiftCarriedForwards = 16;
2719 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2720 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2721
2722 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002723 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2724 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002725 ShiftCarriedForwards = 0;
2726 }
2727
2728 ShiftCarriedForwards += 16;
2729 }
2730 ShiftCarriedForwards -= 16;
2731
2732 // Finish any remaining shifts left by trailing zeros.
2733 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002734 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002735
2736 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002737 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002738
Matheus Almeida3813d572014-06-19 14:39:14 +00002739 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002740}
Jack Carter92995f12012-10-06 00:53:28 +00002741
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002742bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002743 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002744 const MCOperand &ImmOp = Inst.getOperand(1);
2745 assert(ImmOp.isImm() && "expected immediate operand kind");
2746 const MCOperand &DstRegOp = Inst.getOperand(0);
2747 assert(DstRegOp.isReg() && "expected register operand kind");
2748
2749 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002750 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002751 return true;
2752
2753 return false;
2754}
2755
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002756bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2757 const MCOperand &Offset,
2758 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002759 MCStreamer &Out,
2760 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002761 // la can't produce a usable address when addresses are 64-bit.
2762 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2763 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2764 // We currently can't do this because we depend on the equality
2765 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2766 Error(IDLoc, "la used to load 64-bit address");
2767 // Continue as if we had 'dla' instead.
2768 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002769 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002770 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002771
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002772 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002773 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002774 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002775 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002776 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002777
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002778 if (!Offset.isImm())
2779 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002780 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002781
Scott Egerton24557012016-01-21 15:11:01 +00002782 if (!ABI.ArePtrs64bit()) {
2783 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2784 Is32BitAddress = true;
2785 }
2786
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002787 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002788 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002789}
2790
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002791bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2792 unsigned DstReg, unsigned SrcReg,
2793 bool Is32BitSym, SMLoc IDLoc,
2794 MCStreamer &Out,
2795 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002796 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002797 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002798 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002799 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002800
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002801 if (inPicMode() && ABI.IsO32()) {
2802 MCValue Res;
2803 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2804 Error(IDLoc, "expected relocatable expression");
2805 return true;
2806 }
2807 if (Res.getSymB() != nullptr) {
2808 Error(IDLoc, "expected relocatable expression with only one symbol");
2809 return true;
2810 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002811
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002812 // The case where the result register is $25 is somewhat special. If the
2813 // symbol in the final relocation is external and not modified with a
2814 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2815 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002816 Res.getConstant() == 0 &&
2817 !(Res.getSymA()->getSymbol().isInSection() ||
2818 Res.getSymA()->getSymbol().isTemporary() ||
2819 (Res.getSymA()->getSymbol().isELF() &&
2820 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2821 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002822 const MCExpr *CallExpr =
2823 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2824 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2825 MCOperand::createExpr(CallExpr), IDLoc, STI);
2826 return false;
2827 }
2828
2829 // The remaining cases are:
2830 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2831 // >addiu $tmp, $tmp, %lo(offset)
2832 // >addiu $rd, $tmp, $rs
2833 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2834 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2835 // >addiu $rd, $tmp, $rs
2836 // The addiu's marked with a '>' may be omitted if they are redundant. If
2837 // this happens then the last instruction must use $rd as the result
2838 // register.
2839 const MipsMCExpr *GotExpr =
2840 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2841 const MCExpr *LoExpr = nullptr;
2842 if (Res.getSymA()->getSymbol().isInSection() ||
2843 Res.getSymA()->getSymbol().isTemporary())
2844 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2845 else if (Res.getConstant() != 0) {
2846 // External symbols fully resolve the symbol with just the %got(symbol)
2847 // but we must still account for any offset to the symbol for expressions
2848 // like symbol+8.
2849 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2850 }
2851
2852 unsigned TmpReg = DstReg;
2853 if (UseSrcReg &&
2854 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2855 SrcReg)) {
2856 // If $rs is the same as $rd, we need to use AT.
2857 // If it is not available we exit.
2858 unsigned ATReg = getATReg(IDLoc);
2859 if (!ATReg)
2860 return true;
2861 TmpReg = ATReg;
2862 }
2863
2864 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2865 MCOperand::createExpr(GotExpr), IDLoc, STI);
2866
2867 if (LoExpr)
2868 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2869 IDLoc, STI);
2870
2871 if (UseSrcReg)
2872 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2873
2874 return false;
2875 }
2876
Simon Dardisda96c432017-06-30 15:44:27 +00002877 if (inPicMode() && ABI.ArePtrs64bit()) {
2878 MCValue Res;
2879 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2880 Error(IDLoc, "expected relocatable expression");
2881 return true;
2882 }
2883 if (Res.getSymB() != nullptr) {
2884 Error(IDLoc, "expected relocatable expression with only one symbol");
2885 return true;
2886 }
2887
2888 // The case where the result register is $25 is somewhat special. If the
2889 // symbol in the final relocation is external and not modified with a
2890 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2891 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2892 Res.getConstant() == 0 &&
2893 !(Res.getSymA()->getSymbol().isInSection() ||
2894 Res.getSymA()->getSymbol().isTemporary() ||
2895 (Res.getSymA()->getSymbol().isELF() &&
2896 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2897 ELF::STB_LOCAL))) {
2898 const MCExpr *CallExpr =
2899 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2900 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2901 MCOperand::createExpr(CallExpr), IDLoc, STI);
2902 return false;
2903 }
2904
2905 // The remaining cases are:
2906 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2907 // >daddiu $tmp, $tmp, offset
2908 // >daddu $rd, $tmp, $rs
2909 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2910 // this happens then the last instruction must use $rd as the result
2911 // register.
2912 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2913 Res.getSymA(),
2914 getContext());
2915 const MCExpr *LoExpr = nullptr;
2916 if (Res.getConstant() != 0) {
2917 // Symbols fully resolve with just the %got_disp(symbol) but we
2918 // must still account for any offset to the symbol for
2919 // expressions like symbol+8.
2920 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2921
2922 // FIXME: Offsets greater than 16 bits are not yet implemented.
2923 // FIXME: The correct range is a 32-bit sign-extended number.
2924 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2925 Error(IDLoc, "macro instruction uses large offset, which is not "
2926 "currently supported");
2927 return true;
2928 }
2929 }
2930
2931 unsigned TmpReg = DstReg;
2932 if (UseSrcReg &&
2933 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2934 SrcReg)) {
2935 // If $rs is the same as $rd, we need to use AT.
2936 // If it is not available we exit.
2937 unsigned ATReg = getATReg(IDLoc);
2938 if (!ATReg)
2939 return true;
2940 TmpReg = ATReg;
2941 }
2942
2943 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
2944 MCOperand::createExpr(GotExpr), IDLoc, STI);
2945
2946 if (LoExpr)
2947 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2948 IDLoc, STI);
2949
2950 if (UseSrcReg)
2951 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2952
2953 return false;
2954 }
2955
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002956 const MipsMCExpr *HiExpr =
2957 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2958 const MipsMCExpr *LoExpr =
2959 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002960
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002961 // This is the 64-bit symbol address expansion.
2962 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00002963 // We need AT for the 64-bit expansion in the cases where the optional
2964 // source register is the destination register and for the superscalar
2965 // scheduled form.
2966 //
2967 // If it is not available we exit if the destination is the same as the
2968 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002969
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002970 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002971 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002972 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002973 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002974
Simon Dardis3aa8a902017-02-06 12:43:46 +00002975 bool RdRegIsRsReg =
2976 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
2977
2978 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
2979 unsigned ATReg = getATReg(IDLoc);
2980
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002981 // If $rs is the same as $rd:
2982 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2983 // daddiu $at, $at, %higher(sym)
2984 // dsll $at, $at, 16
2985 // daddiu $at, $at, %hi(sym)
2986 // dsll $at, $at, 16
2987 // daddiu $at, $at, %lo(sym)
2988 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002989 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2990 STI);
2991 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2992 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2993 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2994 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2995 IDLoc, STI);
2996 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2997 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2998 IDLoc, STI);
2999 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003000
3001 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00003002 } else if (canUseATReg() && !RdRegIsRsReg) {
3003 unsigned ATReg = getATReg(IDLoc);
3004
3005 // If the $rs is different from $rd or if $rs isn't specified and we
3006 // have $at available:
3007 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3008 // lui $at, %hi(sym)
3009 // daddiu $rd, $rd, %higher(sym)
3010 // daddiu $at, $at, %lo(sym)
3011 // dsll32 $rd, $rd, 0
3012 // daddu $rd, $rd, $at
3013 // (daddu $rd, $rd, $rs)
3014 //
3015 // Which is preferred for superscalar issue.
3016 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3017 STI);
3018 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3019 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3020 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3021 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3022 IDLoc, STI);
3023 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3024 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3025 if (UseSrcReg)
3026 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3027
3028 return false;
3029 } else if (!canUseATReg() && !RdRegIsRsReg) {
3030 // Otherwise, synthesize the address in the destination register
3031 // serially:
3032 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3033 // daddiu $rd, $rd, %higher(sym)
3034 // dsll $rd, $rd, 16
3035 // daddiu $rd, $rd, %hi(sym)
3036 // dsll $rd, $rd, 16
3037 // daddiu $rd, $rd, %lo(sym)
3038 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3039 STI);
3040 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3041 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3042 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3043 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3044 MCOperand::createExpr(HiExpr), IDLoc, STI);
3045 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3046 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3047 MCOperand::createExpr(LoExpr), IDLoc, STI);
3048 if (UseSrcReg)
3049 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3050
3051 return false;
3052 } else {
3053 // We have a case where SrcReg == DstReg and we don't have $at
3054 // available. We can't expand this case, so error out appropriately.
3055 assert(SrcReg == DstReg && !canUseATReg() &&
3056 "Could have expanded dla but didn't?");
3057 reportParseError(IDLoc,
3058 "pseudo-instruction requires $at, which is not available");
3059 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003060 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003061 }
3062
3063 // And now, the 32-bit symbol address expansion:
3064 // If $rs is the same as $rd:
3065 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3066 // ori $at, $at, %lo(sym)
3067 // addu $rd, $at, $rd
3068 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3069 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3070 // ori $rd, $rd, %lo(sym)
3071 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003072 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003073 if (UseSrcReg &&
3074 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003075 // If $rs is the same as $rd, we need to use AT.
3076 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003077 unsigned ATReg = getATReg(IDLoc);
3078 if (!ATReg)
3079 return true;
3080 TmpReg = ATReg;
3081 }
3082
Daniel Sandersa736b372016-04-29 13:33:12 +00003083 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3084 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3085 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003086
Toma Tabacufb9d1252015-06-22 12:08:39 +00003087 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003088 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003089 else
Scott Egerton24557012016-01-21 15:11:01 +00003090 assert(
3091 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003092
Toma Tabacu674825c2015-06-16 12:16:24 +00003093 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003094}
3095
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003096// Each double-precision register DO-D15 overlaps with two of the single
3097// precision registers F0-F31. As an example, all of the following hold true:
3098// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3099static unsigned nextReg(unsigned Reg) {
3100 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3101 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3102 switch (Reg) {
3103 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3104 case Mips::ZERO: return Mips::AT;
3105 case Mips::AT: return Mips::V0;
3106 case Mips::V0: return Mips::V1;
3107 case Mips::V1: return Mips::A0;
3108 case Mips::A0: return Mips::A1;
3109 case Mips::A1: return Mips::A2;
3110 case Mips::A2: return Mips::A3;
3111 case Mips::A3: return Mips::T0;
3112 case Mips::T0: return Mips::T1;
3113 case Mips::T1: return Mips::T2;
3114 case Mips::T2: return Mips::T3;
3115 case Mips::T3: return Mips::T4;
3116 case Mips::T4: return Mips::T5;
3117 case Mips::T5: return Mips::T6;
3118 case Mips::T6: return Mips::T7;
3119 case Mips::T7: return Mips::S0;
3120 case Mips::S0: return Mips::S1;
3121 case Mips::S1: return Mips::S2;
3122 case Mips::S2: return Mips::S3;
3123 case Mips::S3: return Mips::S4;
3124 case Mips::S4: return Mips::S5;
3125 case Mips::S5: return Mips::S6;
3126 case Mips::S6: return Mips::S7;
3127 case Mips::S7: return Mips::T8;
3128 case Mips::T8: return Mips::T9;
3129 case Mips::T9: return Mips::K0;
3130 case Mips::K0: return Mips::K1;
3131 case Mips::K1: return Mips::GP;
3132 case Mips::GP: return Mips::SP;
3133 case Mips::SP: return Mips::FP;
3134 case Mips::FP: return Mips::RA;
3135 case Mips::RA: return Mips::ZERO;
3136 case Mips::D0: return Mips::F1;
3137 case Mips::D1: return Mips::F3;
3138 case Mips::D2: return Mips::F5;
3139 case Mips::D3: return Mips::F7;
3140 case Mips::D4: return Mips::F9;
3141 case Mips::D5: return Mips::F11;
3142 case Mips::D6: return Mips::F13;
3143 case Mips::D7: return Mips::F15;
3144 case Mips::D8: return Mips::F17;
3145 case Mips::D9: return Mips::F19;
3146 case Mips::D10: return Mips::F21;
3147 case Mips::D11: return Mips::F23;
3148 case Mips::D12: return Mips::F25;
3149 case Mips::D13: return Mips::F27;
3150 case Mips::D14: return Mips::F29;
3151 case Mips::D15: return Mips::F31;
3152 }
3153}
3154
3155// FIXME: This method is too general. In principle we should compute the number
3156// of instructions required to synthesize the immediate inline compared to
3157// synthesizing the address inline and relying on non .text sections.
3158// For static O32 and N32 this may yield a small benefit, for static N64 this is
3159// likely to yield a much larger benefit as we have to synthesize a 64bit
3160// address to load a 64 bit value.
3161bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3162 MCSymbol *Sym) {
3163 unsigned ATReg = getATReg(IDLoc);
3164 if (!ATReg)
3165 return true;
3166
3167 if(IsPicEnabled) {
3168 const MCExpr *GotSym =
3169 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3170 const MipsMCExpr *GotExpr =
3171 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3172
3173 if(isABI_O32() || isABI_N32()) {
3174 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3175 IDLoc, STI);
3176 } else { //isABI_N64()
3177 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3178 IDLoc, STI);
3179 }
3180 } else { //!IsPicEnabled
3181 const MCExpr *HiSym =
3182 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3183 const MipsMCExpr *HiExpr =
3184 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3185
3186 // FIXME: This is technically correct but gives a different result to gas,
3187 // but gas is incomplete there (it has a fixme noting it doesn't work with
3188 // 64-bit addresses).
3189 // FIXME: With -msym32 option, the address expansion for N64 should probably
3190 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3191 // symbol's value is considered sign extended.
3192 if(isABI_O32() || isABI_N32()) {
3193 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3194 } else { //isABI_N64()
3195 const MCExpr *HighestSym =
3196 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3197 const MipsMCExpr *HighestExpr =
3198 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3199 const MCExpr *HigherSym =
3200 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3201 const MipsMCExpr *HigherExpr =
3202 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3203
3204 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3205 STI);
3206 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3207 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3208 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3209 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3210 IDLoc, STI);
3211 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3212 }
3213 }
3214 return false;
3215}
3216
3217bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3218 bool Is64FPU, SMLoc IDLoc,
3219 MCStreamer &Out,
3220 const MCSubtargetInfo *STI) {
3221 MipsTargetStreamer &TOut = getTargetStreamer();
3222 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3223 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3224 "Invalid instruction operand.");
3225
3226 unsigned FirstReg = Inst.getOperand(0).getReg();
3227 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3228
3229 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3230 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3231 // exponent field), convert it to double (e.g. 1 to 1.0)
3232 if ((HiImmOp64 & 0x7ff00000) == 0) {
3233 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3234 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3235 }
3236
3237 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3238 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3239
3240 if (IsSingle) {
3241 // Conversion of a double in an uint64_t to a float in a uint32_t,
3242 // retaining the bit pattern of a float.
3243 uint32_t ImmOp32;
3244 double doubleImm = BitsToDouble(ImmOp64);
3245 float tmp_float = static_cast<float>(doubleImm);
3246 ImmOp32 = FloatToBits(tmp_float);
3247
3248 if (IsGPR) {
3249 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3250 Out, STI))
3251 return true;
3252 return false;
3253 } else {
3254 unsigned ATReg = getATReg(IDLoc);
3255 if (!ATReg)
3256 return true;
3257 if (LoImmOp64 == 0) {
3258 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3259 Out, STI))
3260 return true;
3261 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3262 return false;
3263 }
3264
3265 MCSection *CS = getStreamer().getCurrentSectionOnly();
3266 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3267 // where appropriate.
3268 MCSection *ReadOnlySection = getContext().getELFSection(
3269 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3270
3271 MCSymbol *Sym = getContext().createTempSymbol();
3272 const MCExpr *LoSym =
3273 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3274 const MipsMCExpr *LoExpr =
3275 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3276
3277 getStreamer().SwitchSection(ReadOnlySection);
3278 getStreamer().EmitLabel(Sym, IDLoc);
3279 getStreamer().EmitIntValue(ImmOp32, 4);
3280 getStreamer().SwitchSection(CS);
3281
3282 if(emitPartialAddress(TOut, IDLoc, Sym))
3283 return true;
3284 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3285 MCOperand::createExpr(LoExpr), IDLoc, STI);
3286 }
3287 return false;
3288 }
3289
3290 // if(!IsSingle)
3291 unsigned ATReg = getATReg(IDLoc);
3292 if (!ATReg)
3293 return true;
3294
3295 if (IsGPR) {
3296 if (LoImmOp64 == 0) {
3297 if(isABI_N32() || isABI_N64()) {
3298 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3299 IDLoc, Out, STI))
3300 return true;
3301 return false;
3302 } else {
3303 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3304 IDLoc, Out, STI))
3305 return true;
3306
3307 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3308 IDLoc, Out, STI))
3309 return true;
3310 return false;
3311 }
3312 }
3313
3314 MCSection *CS = getStreamer().getCurrentSectionOnly();
3315 MCSection *ReadOnlySection = getContext().getELFSection(
3316 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3317
3318 MCSymbol *Sym = getContext().createTempSymbol();
3319 const MCExpr *LoSym =
3320 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3321 const MipsMCExpr *LoExpr =
3322 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3323
3324 getStreamer().SwitchSection(ReadOnlySection);
3325 getStreamer().EmitLabel(Sym, IDLoc);
3326 getStreamer().EmitIntValue(HiImmOp64, 4);
3327 getStreamer().EmitIntValue(LoImmOp64, 4);
3328 getStreamer().SwitchSection(CS);
3329
3330 if(emitPartialAddress(TOut, IDLoc, Sym))
3331 return true;
3332 if(isABI_N64())
3333 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3334 MCOperand::createExpr(LoExpr), IDLoc, STI);
3335 else
3336 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3337 MCOperand::createExpr(LoExpr), IDLoc, STI);
3338
3339 if(isABI_N32() || isABI_N64())
3340 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3341 else {
3342 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3343 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3344 }
3345 return false;
3346 } else { // if(!IsGPR && !IsSingle)
3347 if ((LoImmOp64 == 0) &&
3348 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3349 // FIXME: In the case where the constant is zero, we can load the
3350 // register directly from the zero register.
3351 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3352 Out, STI))
3353 return true;
3354 if (isABI_N32() || isABI_N64())
3355 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3356 else if (hasMips32r2()) {
3357 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3358 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3359 } else {
3360 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3361 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3362 }
3363 return false;
3364 }
3365
3366 MCSection *CS = getStreamer().getCurrentSectionOnly();
3367 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3368 // where appropriate.
3369 MCSection *ReadOnlySection = getContext().getELFSection(
3370 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3371
3372 MCSymbol *Sym = getContext().createTempSymbol();
3373 const MCExpr *LoSym =
3374 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3375 const MipsMCExpr *LoExpr =
3376 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3377
3378 getStreamer().SwitchSection(ReadOnlySection);
3379 getStreamer().EmitLabel(Sym, IDLoc);
3380 getStreamer().EmitIntValue(HiImmOp64, 4);
3381 getStreamer().EmitIntValue(LoImmOp64, 4);
3382 getStreamer().SwitchSection(CS);
3383
3384 if(emitPartialAddress(TOut, IDLoc, Sym))
3385 return true;
3386 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3387 MCOperand::createExpr(LoExpr), IDLoc, STI);
3388 }
3389 return false;
3390}
3391
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003392bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3393 MCStreamer &Out,
3394 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003395 MipsTargetStreamer &TOut = getTargetStreamer();
3396
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003397 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3398 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003399
3400 MCOperand Offset = Inst.getOperand(0);
3401 if (Offset.isExpr()) {
3402 Inst.clear();
3403 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003404 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3405 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3406 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003407 } else {
3408 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003409 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003410 // If offset fits into 11 bits then this instruction becomes microMIPS
3411 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003412 if (inMicroMipsMode())
3413 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003414 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003415 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003416 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003417 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003418 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003419 Inst.clear();
3420 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003421 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3422 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3423 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003424 }
3425 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003426 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003427
Zoran Jovanovicada70912015-09-07 11:56:37 +00003428 // If .set reorder is active and branch instruction has a delay slot,
3429 // emit a NOP after it.
3430 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3431 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003432 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003433
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003434 return false;
3435}
3436
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003437bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3438 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003439 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003440 const MCOperand &DstRegOp = Inst.getOperand(0);
3441 assert(DstRegOp.isReg() && "expected register operand kind");
3442
3443 const MCOperand &ImmOp = Inst.getOperand(1);
3444 assert(ImmOp.isImm() && "expected immediate operand kind");
3445
3446 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003447 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3448 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003449
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003450 bool IsLikely = false;
3451
Toma Tabacue1e460d2015-06-11 10:36:10 +00003452 unsigned OpCode = 0;
3453 switch(Inst.getOpcode()) {
3454 case Mips::BneImm:
3455 OpCode = Mips::BNE;
3456 break;
3457 case Mips::BeqImm:
3458 OpCode = Mips::BEQ;
3459 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003460 case Mips::BEQLImmMacro:
3461 OpCode = Mips::BEQL;
3462 IsLikely = true;
3463 break;
3464 case Mips::BNELImmMacro:
3465 OpCode = Mips::BNEL;
3466 IsLikely = true;
3467 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003468 default:
3469 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3470 break;
3471 }
3472
3473 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003474 if (ImmValue == 0) {
3475 if (IsLikely) {
3476 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3477 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3478 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3479 } else
3480 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3481 STI);
3482 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003483 warnIfNoMacro(IDLoc);
3484
3485 unsigned ATReg = getATReg(IDLoc);
3486 if (!ATReg)
3487 return true;
3488
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003489 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003490 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003491 return true;
3492
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003493 if (IsLikely) {
3494 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3495 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3496 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3497 } else
3498 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003499 }
3500 return false;
3501}
3502
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003503void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00003504 const MCSubtargetInfo *STI, bool IsLoad,
3505 bool IsImmOpnd) {
3506 if (IsLoad) {
3507 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3508 return;
Scott Egertond65377d2016-03-17 10:37:51 +00003509 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003510 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3511}
3512
3513void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3514 const MCSubtargetInfo *STI, bool IsImmOpnd) {
3515 MipsTargetStreamer &TOut = getTargetStreamer();
3516
3517 unsigned DstReg = Inst.getOperand(0).getReg();
3518 unsigned BaseReg = Inst.getOperand(1).getReg();
3519
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003520 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003521 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3522 unsigned DstRegClassID =
3523 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3524 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3525 (DstRegClassID == Mips::GPR64RegClassID);
3526
3527 if (IsImmOpnd) {
3528 // Try to use DstReg as the temporary.
3529 if (IsGPR && (BaseReg != DstReg)) {
3530 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3531 Inst.getOperand(2).getImm(), DstReg, IDLoc,
3532 STI);
3533 return;
3534 }
3535
Matheus Almeida7de68e72014-06-18 14:46:05 +00003536 // At this point we need AT to perform the expansions and we exit if it is
3537 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00003538 unsigned ATReg = getATReg(IDLoc);
3539 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00003540 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003541
3542 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3543 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
3544 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00003545 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00003546
Daniel Sandersfba875f2016-04-29 13:43:45 +00003547 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003548 MCOperand LoOperand = MCOperand::createExpr(
3549 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3550 MCOperand HiOperand = MCOperand::createExpr(
3551 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003552
3553 // Try to use DstReg as the temporary.
3554 if (IsGPR && (BaseReg != DstReg)) {
3555 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3556 LoOperand, DstReg, IDLoc, STI);
3557 return;
3558 }
3559
3560 // At this point we need AT to perform the expansions and we exit if it is
3561 // not available.
3562 unsigned ATReg = getATReg(IDLoc);
3563 if (!ATReg)
3564 return;
3565
3566 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3567 LoOperand, ATReg, IDLoc, STI);
3568}
3569
3570void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3571 const MCSubtargetInfo *STI,
3572 bool IsImmOpnd) {
3573 MipsTargetStreamer &TOut = getTargetStreamer();
3574
3575 unsigned SrcReg = Inst.getOperand(0).getReg();
3576 unsigned BaseReg = Inst.getOperand(1).getReg();
3577
Daniel Sanders241c6792016-05-12 14:01:50 +00003578 if (IsImmOpnd) {
3579 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
3580 Inst.getOperand(2).getImm(),
3581 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3582 return;
3583 }
3584
Daniel Sandersfba875f2016-04-29 13:43:45 +00003585 unsigned ATReg = getATReg(IDLoc);
3586 if (!ATReg)
3587 return;
3588
Daniel Sandersfba875f2016-04-29 13:43:45 +00003589 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003590 MCOperand LoOperand = MCOperand::createExpr(
3591 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3592 MCOperand HiOperand = MCOperand::createExpr(
3593 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003594 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3595 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003596}
3597
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003598bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3599 MCStreamer &Out,
3600 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003601 unsigned OpNum = Inst.getNumOperands();
3602 unsigned Opcode = Inst.getOpcode();
3603 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3604
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003605 assert(Inst.getOperand(OpNum - 1).isImm() &&
3606 Inst.getOperand(OpNum - 2).isReg() &&
3607 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003608
3609 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3610 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003611 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3612 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3613 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3614 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003615 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003616 if (inMicroMipsMode() && hasMips32r6())
3617 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3618 else
3619 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3620 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003621
3622 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003623 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003624 return false;
3625}
3626
Toma Tabacu1a108322015-06-17 13:20:24 +00003627bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003628 MCStreamer &Out,
3629 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003630 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003631 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003632 unsigned PseudoOpcode = Inst.getOpcode();
3633 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003634 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003635 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3636
3637 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003638 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003639
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003640 unsigned TrgReg;
3641 if (TrgOp.isReg())
3642 TrgReg = TrgOp.getReg();
3643 else if (TrgOp.isImm()) {
3644 warnIfNoMacro(IDLoc);
3645 EmittedNoMacroWarning = true;
3646
3647 TrgReg = getATReg(IDLoc);
3648 if (!TrgReg)
3649 return true;
3650
3651 switch(PseudoOpcode) {
3652 default:
3653 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3654 case Mips::BLTImmMacro:
3655 PseudoOpcode = Mips::BLT;
3656 break;
3657 case Mips::BLEImmMacro:
3658 PseudoOpcode = Mips::BLE;
3659 break;
3660 case Mips::BGEImmMacro:
3661 PseudoOpcode = Mips::BGE;
3662 break;
3663 case Mips::BGTImmMacro:
3664 PseudoOpcode = Mips::BGT;
3665 break;
3666 case Mips::BLTUImmMacro:
3667 PseudoOpcode = Mips::BLTU;
3668 break;
3669 case Mips::BLEUImmMacro:
3670 PseudoOpcode = Mips::BLEU;
3671 break;
3672 case Mips::BGEUImmMacro:
3673 PseudoOpcode = Mips::BGEU;
3674 break;
3675 case Mips::BGTUImmMacro:
3676 PseudoOpcode = Mips::BGTU;
3677 break;
3678 case Mips::BLTLImmMacro:
3679 PseudoOpcode = Mips::BLTL;
3680 break;
3681 case Mips::BLELImmMacro:
3682 PseudoOpcode = Mips::BLEL;
3683 break;
3684 case Mips::BGELImmMacro:
3685 PseudoOpcode = Mips::BGEL;
3686 break;
3687 case Mips::BGTLImmMacro:
3688 PseudoOpcode = Mips::BGTL;
3689 break;
3690 case Mips::BLTULImmMacro:
3691 PseudoOpcode = Mips::BLTUL;
3692 break;
3693 case Mips::BLEULImmMacro:
3694 PseudoOpcode = Mips::BLEUL;
3695 break;
3696 case Mips::BGEULImmMacro:
3697 PseudoOpcode = Mips::BGEUL;
3698 break;
3699 case Mips::BGTULImmMacro:
3700 PseudoOpcode = Mips::BGTUL;
3701 break;
3702 }
3703
3704 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003705 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003706 return true;
3707 }
3708
Toma Tabacu1a108322015-06-17 13:20:24 +00003709 switch (PseudoOpcode) {
3710 case Mips::BLT:
3711 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003712 case Mips::BLTL:
3713 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003714 AcceptsEquality = false;
3715 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003716 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3717 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003718 ZeroSrcOpcode = Mips::BGTZ;
3719 ZeroTrgOpcode = Mips::BLTZ;
3720 break;
3721 case Mips::BLE:
3722 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003723 case Mips::BLEL:
3724 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003725 AcceptsEquality = true;
3726 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003727 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3728 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003729 ZeroSrcOpcode = Mips::BGEZ;
3730 ZeroTrgOpcode = Mips::BLEZ;
3731 break;
3732 case Mips::BGE:
3733 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003734 case Mips::BGEL:
3735 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003736 AcceptsEquality = true;
3737 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003738 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3739 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003740 ZeroSrcOpcode = Mips::BLEZ;
3741 ZeroTrgOpcode = Mips::BGEZ;
3742 break;
3743 case Mips::BGT:
3744 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003745 case Mips::BGTL:
3746 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003747 AcceptsEquality = false;
3748 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003749 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3750 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003751 ZeroSrcOpcode = Mips::BLTZ;
3752 ZeroTrgOpcode = Mips::BGTZ;
3753 break;
3754 default:
3755 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3756 }
3757
Toma Tabacu1a108322015-06-17 13:20:24 +00003758 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3759 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3760 if (IsSrcRegZero && IsTrgRegZero) {
3761 // FIXME: All of these Opcode-specific if's are needed for compatibility
3762 // with GAS' behaviour. However, they may not generate the most efficient
3763 // code in some circumstances.
3764 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003765 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3766 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003767 return false;
3768 }
3769 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003770 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3771 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003772 Warning(IDLoc, "branch is always taken");
3773 return false;
3774 }
3775 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003776 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3777 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003778 Warning(IDLoc, "branch is always taken");
3779 return false;
3780 }
3781 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003782 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3783 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003784 return false;
3785 }
3786 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003787 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3788 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003789 return false;
3790 }
3791 if (AcceptsEquality) {
3792 // If both registers are $0 and the pseudo-branch accepts equality, it
3793 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003794 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3795 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003796 Warning(IDLoc, "branch is always taken");
3797 return false;
3798 }
3799 // If both registers are $0 and the pseudo-branch does not accept
3800 // equality, it will never be taken, so we don't have to emit anything.
3801 return false;
3802 }
3803 if (IsSrcRegZero || IsTrgRegZero) {
3804 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3805 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3806 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3807 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3808 // the pseudo-branch will never be taken, so we don't emit anything.
3809 // This only applies to unsigned pseudo-branches.
3810 return false;
3811 }
3812 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3813 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3814 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3815 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3816 // the pseudo-branch will always be taken, so we emit an unconditional
3817 // branch.
3818 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003819 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3820 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003821 Warning(IDLoc, "branch is always taken");
3822 return false;
3823 }
3824 if (IsUnsigned) {
3825 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3826 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3827 // the pseudo-branch will be taken only when the non-zero register is
3828 // different from 0, so we emit a BNEZ.
3829 //
3830 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3831 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3832 // the pseudo-branch will be taken only when the non-zero register is
3833 // equal to 0, so we emit a BEQZ.
3834 //
3835 // Because only BLEU and BGEU branch on equality, we can use the
3836 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003837 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3838 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3839 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003840 return false;
3841 }
3842 // If we have a signed pseudo-branch and one of the registers is $0,
3843 // we can use an appropriate compare-to-zero branch. We select which one
3844 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003845 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3846 IsSrcRegZero ? TrgReg : SrcReg,
3847 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003848 return false;
3849 }
3850
3851 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3852 // expansions. If it is not available, we return.
3853 unsigned ATRegNum = getATReg(IDLoc);
3854 if (!ATRegNum)
3855 return true;
3856
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003857 if (!EmittedNoMacroWarning)
3858 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003859
3860 // SLT fits well with 2 of our 4 pseudo-branches:
3861 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3862 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3863 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3864 // This is accomplished by using a BNEZ with the result of the SLT.
3865 //
3866 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3867 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3868 // Because only BGE and BLE branch on equality, we can use the
3869 // AcceptsEquality variable to decide when to emit the BEQZ.
3870 // Note that the order of the SLT arguments doesn't change between
3871 // opposites.
3872 //
3873 // The same applies to the unsigned variants, except that SLTu is used
3874 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003875 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3876 ReverseOrderSLT ? TrgReg : SrcReg,
3877 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003878
Daniel Sandersa736b372016-04-29 13:33:12 +00003879 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3880 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3881 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3882 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003883 return false;
3884}
3885
Simon Dardis509da1a2017-02-13 16:06:48 +00003886// Expand a integer division macro.
3887//
3888// Notably we don't have to emit a warning when encountering $rt as the $zero
3889// register, or 0 as an immediate. processInstruction() has already done that.
3890//
3891// The destination register can only be $zero when expanding (S)DivIMacro or
3892// D(S)DivMacro.
3893
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003894bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3895 const MCSubtargetInfo *STI, const bool IsMips64,
3896 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003897 MipsTargetStreamer &TOut = getTargetStreamer();
3898
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003899 warnIfNoMacro(IDLoc);
3900
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003901 const MCOperand &RdRegOp = Inst.getOperand(0);
3902 assert(RdRegOp.isReg() && "expected register operand kind");
3903 unsigned RdReg = RdRegOp.getReg();
3904
3905 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003906 assert(RsRegOp.isReg() && "expected register operand kind");
3907 unsigned RsReg = RsRegOp.getReg();
3908
Simon Dardis12850ee2017-01-31 10:49:24 +00003909 unsigned RtReg;
3910 int64_t ImmValue;
3911
3912 const MCOperand &RtOp = Inst.getOperand(2);
3913 assert((RtOp.isReg() || RtOp.isImm()) &&
3914 "expected register or immediate operand kind");
3915 if (RtOp.isReg())
3916 RtReg = RtOp.getReg();
3917 else
3918 ImmValue = RtOp.getImm();
3919
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003920 unsigned DivOp;
3921 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003922 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003923
3924 if (IsMips64) {
3925 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3926 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003927 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003928 } else {
3929 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3930 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003931 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003932 }
3933
3934 bool UseTraps = useTraps();
3935
Simon Dardis12850ee2017-01-31 10:49:24 +00003936 if (RtOp.isImm()) {
3937 unsigned ATReg = getATReg(IDLoc);
3938 if (!ATReg)
3939 return true;
3940
3941 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003942 if (UseTraps)
3943 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3944 else
3945 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3946 return false;
3947 }
3948
3949 if (ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003950 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003951 return false;
3952 } else if (Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003953 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003954 return false;
3955 } else {
3956 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
3957 false, Inst.getLoc(), Out, STI))
3958 return true;
3959 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
3960 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
3961 return false;
3962 }
3963 return true;
3964 }
3965
Simon Dardis509da1a2017-02-13 16:06:48 +00003966 // If the macro expansion of (d)div(u) would always trap or break, insert
3967 // the trap/break and exit. This gives a different result to GAS. GAS has
3968 // an inconsistency/missed optimization in that not all cases are handled
3969 // equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003970 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003971 if (UseTraps) {
3972 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003973 return false;
3974 }
Simon Dardis509da1a2017-02-13 16:06:48 +00003975 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3976 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003977 }
3978
Simon Dardis509da1a2017-02-13 16:06:48 +00003979 // Temporary label for first branch traget
3980 MCContext &Context = TOut.getStreamer().getContext();
3981 MCSymbol *BrTarget;
3982 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003983
3984 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003985 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003986 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003987 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00003988 BrTarget = Context.createTempSymbol();
3989 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
3990 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003991 }
3992
Daniel Sandersa736b372016-04-29 13:33:12 +00003993 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003994
3995 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003996 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003997
3998 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003999 if (!UseTraps)
4000 TOut.getStreamer().EmitLabel(BrTarget);
4001
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004002 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004003 return false;
4004 }
4005
4006 unsigned ATReg = getATReg(IDLoc);
4007 if (!ATReg)
4008 return true;
4009
Simon Dardis509da1a2017-02-13 16:06:48 +00004010 if (!UseTraps)
4011 TOut.getStreamer().EmitLabel(BrTarget);
4012
Daniel Sandersa736b372016-04-29 13:33:12 +00004013 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004014
4015 // Temporary label for the second branch target.
4016 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4017 MCOperand LabelOpEnd =
4018 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4019
4020 // Branch to the mflo instruction.
4021 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4022
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004023 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004024 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
4025 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004026 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004027 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004028 }
4029
4030 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004031 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004032 else {
4033 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004034 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004035 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
4036 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004037 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004038
4039 TOut.getStreamer().EmitLabel(BrTargetEnd);
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004040 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004041 return false;
4042}
4043
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004044bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004045 SMLoc IDLoc, MCStreamer &Out,
4046 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004047 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004048
4049 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4050 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4051 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4052
4053 unsigned FirstReg = Inst.getOperand(0).getReg();
4054 unsigned SecondReg = Inst.getOperand(1).getReg();
4055 unsigned ThirdReg = Inst.getOperand(2).getReg();
4056
4057 if (hasMips1() && !hasMips2()) {
4058 unsigned ATReg = getATReg(IDLoc);
4059 if (!ATReg)
4060 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004061 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4062 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4063 TOut.emitNop(IDLoc, STI);
4064 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4065 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4066 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4067 TOut.emitNop(IDLoc, STI);
4068 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4069 : Mips::CVT_W_S,
4070 FirstReg, SecondReg, IDLoc, STI);
4071 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4072 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004073 return false;
4074 }
4075
Daniel Sandersa736b372016-04-29 13:33:12 +00004076 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4077 : Mips::TRUNC_W_S,
4078 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004079
4080 return false;
4081}
4082
Daniel Sanders6394ee52015-10-15 14:52:58 +00004083bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004084 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004085 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004086 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004087 }
4088
Toma Tabacud88d79c2015-06-23 14:39:42 +00004089 const MCOperand &DstRegOp = Inst.getOperand(0);
4090 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004091 const MCOperand &SrcRegOp = Inst.getOperand(1);
4092 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004093 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4094 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4095
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004096 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004097 unsigned DstReg = DstRegOp.getReg();
4098 unsigned SrcReg = SrcRegOp.getReg();
4099 int64_t OffsetValue = OffsetImmOp.getImm();
4100
4101 // NOTE: We always need AT for ULHU, as it is always used as the source
4102 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004103 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004104 unsigned ATReg = getATReg(IDLoc);
4105 if (!ATReg)
4106 return true;
4107
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004108 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4109 if (IsLargeOffset) {
4110 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4111 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004112 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004113 }
4114
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004115 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4116 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4117 if (isLittle())
4118 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004119
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004120 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4121 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004122
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004123 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4124 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004125
Daniel Sandersa736b372016-04-29 13:33:12 +00004126 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004127 FirstOffset, IDLoc, STI);
4128 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004129 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004130 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004131
4132 return false;
4133}
4134
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004135bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004136 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004137 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004138 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004139 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004140
4141 const MCOperand &DstRegOp = Inst.getOperand(0);
4142 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004143 const MCOperand &SrcRegOp = Inst.getOperand(1);
4144 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004145 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4146 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4147
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004148 MipsTargetStreamer &TOut = getTargetStreamer();
4149 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004150 unsigned SrcReg = SrcRegOp.getReg();
4151 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004152
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004153 warnIfNoMacro(IDLoc);
4154 unsigned ATReg = getATReg(IDLoc);
4155 if (!ATReg)
4156 return true;
4157
4158 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4159 if (IsLargeOffset) {
4160 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4161 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004162 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004163 }
4164
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004165 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4166 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4167 if (isLittle())
4168 std::swap(FirstOffset, SecondOffset);
4169
4170 if (IsLargeOffset) {
4171 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4172 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4173 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4174 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4175 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4176 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004177 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004178 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4179 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4180 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004181 }
4182
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004183 return false;
4184}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004185
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004186bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4187 const MCSubtargetInfo *STI) {
4188 if (hasMips32r6() || hasMips64r6()) {
4189 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4190 }
4191
4192 const MCOperand &DstRegOp = Inst.getOperand(0);
4193 assert(DstRegOp.isReg() && "expected register operand kind");
4194 const MCOperand &SrcRegOp = Inst.getOperand(1);
4195 assert(SrcRegOp.isReg() && "expected register operand kind");
4196 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4197 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4198
4199 MipsTargetStreamer &TOut = getTargetStreamer();
4200 unsigned DstReg = DstRegOp.getReg();
4201 unsigned SrcReg = SrcRegOp.getReg();
4202 int64_t OffsetValue = OffsetImmOp.getImm();
4203
4204 // Compute left/right load/store offsets.
4205 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4206 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4207 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4208 if (isLittle())
4209 std::swap(LxlOffset, LxrOffset);
4210
4211 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4212 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4213 unsigned TmpReg = SrcReg;
4214 if (IsLargeOffset || DoMove) {
4215 warnIfNoMacro(IDLoc);
4216 TmpReg = getATReg(IDLoc);
4217 if (!TmpReg)
4218 return true;
4219 }
4220
4221 if (IsLargeOffset) {
4222 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4223 IDLoc, Out, STI))
4224 return true;
4225 }
4226
4227 if (DoMove)
4228 std::swap(DstReg, TmpReg);
4229
4230 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4231 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4232 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4233 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4234
4235 if (DoMove)
4236 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004237
4238 return false;
4239}
4240
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004241bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004242 MCStreamer &Out,
4243 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004244 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004245
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004246 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4247 assert(Inst.getOperand(0).isReg() &&
4248 Inst.getOperand(1).isReg() &&
4249 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004250
4251 unsigned ATReg = Mips::NoRegister;
4252 unsigned FinalDstReg = Mips::NoRegister;
4253 unsigned DstReg = Inst.getOperand(0).getReg();
4254 unsigned SrcReg = Inst.getOperand(1).getReg();
4255 int64_t ImmValue = Inst.getOperand(2).getImm();
4256
Simon Dardisaa208812017-02-24 14:34:32 +00004257 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004258
4259 unsigned FinalOpcode = Inst.getOpcode();
4260
4261 if (DstReg == SrcReg) {
4262 ATReg = getATReg(Inst.getLoc());
4263 if (!ATReg)
4264 return true;
4265 FinalDstReg = DstReg;
4266 DstReg = ATReg;
4267 }
4268
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004269 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004270 switch (FinalOpcode) {
4271 default:
4272 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004273 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004274 FinalOpcode = Mips::ADD;
4275 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004276 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004277 FinalOpcode = Mips::ADDu;
4278 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004279 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004280 FinalOpcode = Mips::AND;
4281 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004282 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004283 FinalOpcode = Mips::NOR;
4284 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004285 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004286 FinalOpcode = Mips::OR;
4287 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004288 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004289 FinalOpcode = Mips::SLT;
4290 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004291 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004292 FinalOpcode = Mips::SLTu;
4293 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004294 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004295 FinalOpcode = Mips::XOR;
4296 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004297 case Mips::ADDi_MM:
4298 FinalOpcode = Mips::ADD_MM;
4299 break;
4300 case Mips::ADDiu_MM:
4301 FinalOpcode = Mips::ADDu_MM;
4302 break;
4303 case Mips::ANDi_MM:
4304 FinalOpcode = Mips::AND_MM;
4305 break;
4306 case Mips::ORi_MM:
4307 FinalOpcode = Mips::OR_MM;
4308 break;
4309 case Mips::SLTi_MM:
4310 FinalOpcode = Mips::SLT_MM;
4311 break;
4312 case Mips::SLTiu_MM:
4313 FinalOpcode = Mips::SLTu_MM;
4314 break;
4315 case Mips::XORi_MM:
4316 FinalOpcode = Mips::XOR_MM;
4317 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004318 case Mips::ANDi64:
4319 FinalOpcode = Mips::AND64;
4320 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004321 case Mips::NORImm64:
4322 FinalOpcode = Mips::NOR64;
4323 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004324 case Mips::ORi64:
4325 FinalOpcode = Mips::OR64;
4326 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004327 case Mips::SLTImm64:
4328 FinalOpcode = Mips::SLT64;
4329 break;
4330 case Mips::SLTUImm64:
4331 FinalOpcode = Mips::SLTu64;
4332 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004333 case Mips::XORi64:
4334 FinalOpcode = Mips::XOR64;
4335 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004336 }
4337
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004338 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004339 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004340 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004341 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004342 return false;
4343 }
4344 return true;
4345}
4346
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004347bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4348 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004349 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004350 unsigned ATReg = Mips::NoRegister;
4351 unsigned DReg = Inst.getOperand(0).getReg();
4352 unsigned SReg = Inst.getOperand(1).getReg();
4353 unsigned TReg = Inst.getOperand(2).getReg();
4354 unsigned TmpReg = DReg;
4355
4356 unsigned FirstShift = Mips::NOP;
4357 unsigned SecondShift = Mips::NOP;
4358
4359 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004360 if (DReg == SReg) {
4361 TmpReg = getATReg(Inst.getLoc());
4362 if (!TmpReg)
4363 return true;
4364 }
4365
4366 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004367 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4368 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004369 return false;
4370 }
4371
4372 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004373 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004374 return false;
4375 }
4376
4377 return true;
4378 }
4379
4380 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004381 switch (Inst.getOpcode()) {
4382 default:
4383 llvm_unreachable("unexpected instruction opcode");
4384 case Mips::ROL:
4385 FirstShift = Mips::SRLV;
4386 SecondShift = Mips::SLLV;
4387 break;
4388 case Mips::ROR:
4389 FirstShift = Mips::SLLV;
4390 SecondShift = Mips::SRLV;
4391 break;
4392 }
4393
4394 ATReg = getATReg(Inst.getLoc());
4395 if (!ATReg)
4396 return true;
4397
Daniel Sandersa736b372016-04-29 13:33:12 +00004398 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4399 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4400 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4401 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004402
4403 return false;
4404 }
4405
4406 return true;
4407}
4408
4409bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004410 MCStreamer &Out,
4411 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004412 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004413 unsigned ATReg = Mips::NoRegister;
4414 unsigned DReg = Inst.getOperand(0).getReg();
4415 unsigned SReg = Inst.getOperand(1).getReg();
4416 int64_t ImmValue = Inst.getOperand(2).getImm();
4417
4418 unsigned FirstShift = Mips::NOP;
4419 unsigned SecondShift = Mips::NOP;
4420
4421 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004422 if (Inst.getOpcode() == Mips::ROLImm) {
4423 uint64_t MaxShift = 32;
4424 uint64_t ShiftValue = ImmValue;
4425 if (ImmValue != 0)
4426 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004427 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004428 return false;
4429 }
4430
4431 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004432 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004433 return false;
4434 }
4435
4436 return true;
4437 }
4438
4439 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004440 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004441 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004442 return false;
4443 }
4444
4445 switch (Inst.getOpcode()) {
4446 default:
4447 llvm_unreachable("unexpected instruction opcode");
4448 case Mips::ROLImm:
4449 FirstShift = Mips::SLL;
4450 SecondShift = Mips::SRL;
4451 break;
4452 case Mips::RORImm:
4453 FirstShift = Mips::SRL;
4454 SecondShift = Mips::SLL;
4455 break;
4456 }
4457
4458 ATReg = getATReg(Inst.getLoc());
4459 if (!ATReg)
4460 return true;
4461
Daniel Sandersa736b372016-04-29 13:33:12 +00004462 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4463 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4464 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004465
4466 return false;
4467 }
4468
4469 return true;
4470}
4471
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004472bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4473 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004474 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004475 unsigned ATReg = Mips::NoRegister;
4476 unsigned DReg = Inst.getOperand(0).getReg();
4477 unsigned SReg = Inst.getOperand(1).getReg();
4478 unsigned TReg = Inst.getOperand(2).getReg();
4479 unsigned TmpReg = DReg;
4480
4481 unsigned FirstShift = Mips::NOP;
4482 unsigned SecondShift = Mips::NOP;
4483
4484 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004485 if (TmpReg == SReg) {
4486 TmpReg = getATReg(Inst.getLoc());
4487 if (!TmpReg)
4488 return true;
4489 }
4490
4491 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004492 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4493 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004494 return false;
4495 }
4496
4497 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004498 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004499 return false;
4500 }
4501
4502 return true;
4503 }
4504
4505 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004506 switch (Inst.getOpcode()) {
4507 default:
4508 llvm_unreachable("unexpected instruction opcode");
4509 case Mips::DROL:
4510 FirstShift = Mips::DSRLV;
4511 SecondShift = Mips::DSLLV;
4512 break;
4513 case Mips::DROR:
4514 FirstShift = Mips::DSLLV;
4515 SecondShift = Mips::DSRLV;
4516 break;
4517 }
4518
4519 ATReg = getATReg(Inst.getLoc());
4520 if (!ATReg)
4521 return true;
4522
Daniel Sandersa736b372016-04-29 13:33:12 +00004523 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4524 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4525 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4526 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004527
4528 return false;
4529 }
4530
4531 return true;
4532}
4533
4534bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004535 MCStreamer &Out,
4536 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004537 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004538 unsigned ATReg = Mips::NoRegister;
4539 unsigned DReg = Inst.getOperand(0).getReg();
4540 unsigned SReg = Inst.getOperand(1).getReg();
4541 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4542
4543 unsigned FirstShift = Mips::NOP;
4544 unsigned SecondShift = Mips::NOP;
4545
4546 MCInst TmpInst;
4547
4548 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004549 unsigned FinalOpcode = Mips::NOP;
4550 if (ImmValue == 0)
4551 FinalOpcode = Mips::DROTR;
4552 else if (ImmValue % 32 == 0)
4553 FinalOpcode = Mips::DROTR32;
4554 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4555 if (Inst.getOpcode() == Mips::DROLImm)
4556 FinalOpcode = Mips::DROTR32;
4557 else
4558 FinalOpcode = Mips::DROTR;
4559 } else if (ImmValue >= 33) {
4560 if (Inst.getOpcode() == Mips::DROLImm)
4561 FinalOpcode = Mips::DROTR;
4562 else
4563 FinalOpcode = Mips::DROTR32;
4564 }
4565
4566 uint64_t ShiftValue = ImmValue % 32;
4567 if (Inst.getOpcode() == Mips::DROLImm)
4568 ShiftValue = (32 - ImmValue % 32) % 32;
4569
Daniel Sandersa736b372016-04-29 13:33:12 +00004570 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004571
4572 return false;
4573 }
4574
4575 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004576 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004577 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004578 return false;
4579 }
4580
4581 switch (Inst.getOpcode()) {
4582 default:
4583 llvm_unreachable("unexpected instruction opcode");
4584 case Mips::DROLImm:
4585 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4586 FirstShift = Mips::DSLL;
4587 SecondShift = Mips::DSRL32;
4588 }
4589 if (ImmValue == 32) {
4590 FirstShift = Mips::DSLL32;
4591 SecondShift = Mips::DSRL32;
4592 }
4593 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4594 FirstShift = Mips::DSLL32;
4595 SecondShift = Mips::DSRL;
4596 }
4597 break;
4598 case Mips::DRORImm:
4599 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4600 FirstShift = Mips::DSRL;
4601 SecondShift = Mips::DSLL32;
4602 }
4603 if (ImmValue == 32) {
4604 FirstShift = Mips::DSRL32;
4605 SecondShift = Mips::DSLL32;
4606 }
4607 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4608 FirstShift = Mips::DSRL32;
4609 SecondShift = Mips::DSLL;
4610 }
4611 break;
4612 }
4613
4614 ATReg = getATReg(Inst.getLoc());
4615 if (!ATReg)
4616 return true;
4617
Daniel Sandersa736b372016-04-29 13:33:12 +00004618 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4619 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4620 Inst.getLoc(), STI);
4621 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004622
4623 return false;
4624 }
4625
4626 return true;
4627}
4628
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004629bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4630 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004631 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004632 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4633 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4634
Daniel Sandersa736b372016-04-29 13:33:12 +00004635 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004636 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004637 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004638 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004639 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4640 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004641
4642 return false;
4643}
4644
Simon Dardis3c82a642017-02-08 16:25:05 +00004645bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4646 const MCSubtargetInfo *STI) {
4647 MipsTargetStreamer &TOut = getTargetStreamer();
4648 unsigned ATReg = Mips::NoRegister;
4649 unsigned DstReg = Inst.getOperand(0).getReg();
4650 unsigned SrcReg = Inst.getOperand(1).getReg();
4651 int32_t ImmValue = Inst.getOperand(2).getImm();
4652
4653 ATReg = getATReg(IDLoc);
4654 if (!ATReg)
4655 return true;
4656
4657 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI);
4658
4659 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4660 SrcReg, ATReg, IDLoc, STI);
4661
4662 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4663
4664 return false;
4665}
4666
4667bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4668 const MCSubtargetInfo *STI) {
4669 MipsTargetStreamer &TOut = getTargetStreamer();
4670 unsigned ATReg = Mips::NoRegister;
4671 unsigned DstReg = Inst.getOperand(0).getReg();
4672 unsigned SrcReg = Inst.getOperand(1).getReg();
4673 unsigned TmpReg = Inst.getOperand(2).getReg();
4674
4675 ATReg = getATReg(Inst.getLoc());
4676 if (!ATReg)
4677 return true;
4678
4679 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4680 SrcReg, TmpReg, IDLoc, STI);
4681
4682 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4683
4684 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4685 DstReg, DstReg, 0x1F, IDLoc, STI);
4686
4687 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4688
4689 if (useTraps()) {
4690 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4691 } else {
4692 MCContext & Context = TOut.getStreamer().getContext();
4693 MCSymbol * BrTarget = Context.createTempSymbol();
4694 MCOperand LabelOp =
4695 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4696
4697 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4698 if (AssemblerOptions.back()->isReorder())
4699 TOut.emitNop(IDLoc, STI);
4700 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4701
4702 TOut.getStreamer().EmitLabel(BrTarget);
4703 }
4704 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4705
4706 return false;
4707}
4708
4709bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4710 const MCSubtargetInfo *STI) {
4711 MipsTargetStreamer &TOut = getTargetStreamer();
4712 unsigned ATReg = Mips::NoRegister;
4713 unsigned DstReg = Inst.getOperand(0).getReg();
4714 unsigned SrcReg = Inst.getOperand(1).getReg();
4715 unsigned TmpReg = Inst.getOperand(2).getReg();
4716
4717 ATReg = getATReg(IDLoc);
4718 if (!ATReg)
4719 return true;
4720
4721 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4722 SrcReg, TmpReg, IDLoc, STI);
4723
4724 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4725 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4726 if (useTraps()) {
4727 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4728 } else {
4729 MCContext & Context = TOut.getStreamer().getContext();
4730 MCSymbol * BrTarget = Context.createTempSymbol();
4731 MCOperand LabelOp =
4732 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4733
4734 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4735 if (AssemblerOptions.back()->isReorder())
4736 TOut.emitNop(IDLoc, STI);
4737 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4738
4739 TOut.getStreamer().EmitLabel(BrTarget);
4740 }
4741
4742 return false;
4743}
4744
4745bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4746 const MCSubtargetInfo *STI) {
4747 MipsTargetStreamer &TOut = getTargetStreamer();
4748 unsigned DstReg = Inst.getOperand(0).getReg();
4749 unsigned SrcReg = Inst.getOperand(1).getReg();
4750 unsigned TmpReg = Inst.getOperand(2).getReg();
4751
4752 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4753 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4754
4755 return false;
4756}
4757
Simon Dardisaff4d142016-10-18 14:28:00 +00004758// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4759// lw $<reg+1>>, offset+4($reg2)'
4760// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4761// sw $<reg+1>>, offset+4($reg2)'
4762// for O32.
4763bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4764 MCStreamer &Out,
4765 const MCSubtargetInfo *STI,
4766 bool IsLoad) {
4767 if (!isABI_O32())
4768 return true;
4769
4770 warnIfNoMacro(IDLoc);
4771
4772 MipsTargetStreamer &TOut = getTargetStreamer();
4773 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4774 unsigned FirstReg = Inst.getOperand(0).getReg();
4775 unsigned SecondReg = nextReg(FirstReg);
4776 unsigned BaseReg = Inst.getOperand(1).getReg();
4777 if (!SecondReg)
4778 return true;
4779
4780 warnIfRegIndexIsAT(FirstReg, IDLoc);
4781
4782 assert(Inst.getOperand(2).isImm() &&
4783 "Offset for load macro is not immediate!");
4784
4785 MCOperand &FirstOffset = Inst.getOperand(2);
4786 signed NextOffset = FirstOffset.getImm() + 4;
4787 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4788
4789 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4790 return true;
4791
4792 // For loads, clobber the base register with the second load instead of the
4793 // first if the BaseReg == FirstReg.
4794 if (FirstReg != BaseReg || !IsLoad) {
4795 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4796 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4797 } else {
4798 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4799 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4800 }
4801
4802 return false;
4803}
4804
Simon Dardis43115a12016-11-21 20:30:41 +00004805bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4806 const MCSubtargetInfo *STI) {
4807
4808 warnIfNoMacro(IDLoc);
4809 MipsTargetStreamer &TOut = getTargetStreamer();
4810
4811 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4812 Inst.getOperand(2).getReg() != Mips::ZERO) {
4813 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4814 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4815 IDLoc, STI);
4816 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4817 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4818 return false;
4819 }
4820
4821 unsigned Reg = 0;
4822 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4823 Reg = Inst.getOperand(2).getReg();
4824 } else {
4825 Reg = Inst.getOperand(1).getReg();
4826 }
4827 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4828 return false;
4829}
4830
4831bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4832 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004833 warnIfNoMacro(IDLoc);
4834 MipsTargetStreamer &TOut = getTargetStreamer();
4835
4836 unsigned Opc;
4837 int64_t Imm = Inst.getOperand(2).getImm();
4838 unsigned Reg = Inst.getOperand(1).getReg();
4839
4840 if (Imm == 0) {
4841 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4842 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4843 return false;
4844 } else {
4845
4846 if (Reg == Mips::ZERO) {
4847 Warning(IDLoc, "comparison is always false");
4848 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4849 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4850 return false;
4851 }
4852
4853 if (Imm > -0x8000 && Imm < 0) {
4854 Imm = -Imm;
4855 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4856 } else {
4857 Opc = Mips::XORi;
4858 }
4859 }
4860 if (!isUInt<16>(Imm)) {
4861 unsigned ATReg = getATReg(IDLoc);
4862 if (!ATReg)
4863 return true;
4864
4865 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4866 Out, STI))
4867 return true;
4868
4869 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4870 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4871 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4872 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4873 return false;
4874 }
4875
4876 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4877 Imm, IDLoc, STI);
4878 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4879 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4880 return false;
4881}
4882
Daniel Sandersc5537422016-07-27 13:49:44 +00004883unsigned
4884MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
4885 const OperandVector &Operands) {
4886 switch (Inst.getOpcode()) {
4887 default:
4888 return Match_Success;
4889 case Mips::DATI:
4890 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00004891 case Mips::DATI_MM64R6:
4892 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00004893 if (static_cast<MipsOperand &>(*Operands[1])
4894 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
4895 return Match_Success;
4896 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00004897 }
4898}
Simon Dardis730fdb72017-01-16 13:55:58 +00004899
Matheus Almeida595fcab2014-06-11 15:05:56 +00004900unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00004901 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00004902 // As described by the MIPSR6 spec, daui must not use the zero operand for
4903 // its source operand.
4904 case Mips::DAUI:
4905 case Mips::DAUI_MM64R6:
4906 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4907 Inst.getOperand(1).getReg() == Mips::ZERO_64)
4908 return Match_RequiresNoZeroRegister;
4909 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00004910 // As described by the Mips32r2 spec, the registers Rd and Rs for
4911 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00004912 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00004913 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00004914 case Mips::JALR_HB:
4915 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00004916 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00004917 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4918 return Match_RequiresDifferentSrcAndDst;
4919 return Match_Success;
4920 case Mips::LWP_MM:
4921 case Mips::LWP_MMR6:
4922 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
4923 return Match_RequiresDifferentSrcAndDst;
4924 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00004925 case Mips::SYNC:
4926 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
4927 return Match_NonZeroOperandForSync;
4928 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004929 // As described the MIPSR6 spec, the compact branches that compare registers
4930 // must:
4931 // a) Not use the zero register.
4932 // b) Not use the same register twice.
4933 // c) rs < rt for bnec, beqc.
4934 // NB: For this case, the encoding will swap the operands as their
4935 // ordering doesn't matter. GAS performs this transformation too.
4936 // Hence, that constraint does not have to be enforced.
4937 //
4938 // The compact branches that branch iff the signed addition of two registers
4939 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
4940 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004941 case Mips::BLEZC: case Mips::BLEZC_MMR6:
4942 case Mips::BGEZC: case Mips::BGEZC_MMR6:
4943 case Mips::BGTZC: case Mips::BGTZC_MMR6:
4944 case Mips::BLTZC: case Mips::BLTZC_MMR6:
4945 case Mips::BEQZC: case Mips::BEQZC_MMR6:
4946 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004947 case Mips::BLEZC64:
4948 case Mips::BGEZC64:
4949 case Mips::BGTZC64:
4950 case Mips::BLTZC64:
4951 case Mips::BEQZC64:
4952 case Mips::BNEZC64:
4953 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4954 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004955 return Match_RequiresNoZeroRegister;
4956 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004957 case Mips::BGEC: case Mips::BGEC_MMR6:
4958 case Mips::BLTC: case Mips::BLTC_MMR6:
4959 case Mips::BGEUC: case Mips::BGEUC_MMR6:
4960 case Mips::BLTUC: case Mips::BLTUC_MMR6:
4961 case Mips::BEQC: case Mips::BEQC_MMR6:
4962 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004963 case Mips::BGEC64:
4964 case Mips::BLTC64:
4965 case Mips::BGEUC64:
4966 case Mips::BLTUC64:
4967 case Mips::BEQC64:
4968 case Mips::BNEC64:
4969 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4970 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004971 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00004972 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4973 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004974 return Match_RequiresNoZeroRegister;
4975 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4976 return Match_RequiresDifferentOperands;
4977 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004978 }
Simon Dardis730fdb72017-01-16 13:55:58 +00004979
4980 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
4981 if ((TSFlags & MipsII::HasFCCRegOperand) &&
4982 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
4983 return Match_NoFCCRegisterForCurrentISA;
4984
4985 return Match_Success;
4986
Matheus Almeida595fcab2014-06-11 15:05:56 +00004987}
4988
Daniel Sanders52da7af2015-11-06 12:11:03 +00004989static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
4990 uint64_t ErrorInfo) {
4991 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
4992 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
4993 if (ErrorLoc == SMLoc())
4994 return Loc;
4995 return ErrorLoc;
4996 }
4997 return Loc;
4998}
4999
David Blaikie960ea3f2014-06-08 16:18:35 +00005000bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5001 OperandVector &Operands,
5002 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005003 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005004 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005005 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005006 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005007 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005008
5009 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005010 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005011 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005012 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005013 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005014 case Match_MissingFeature:
5015 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5016 return true;
5017 case Match_InvalidOperand: {
5018 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005019 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005020 if (ErrorInfo >= Operands.size())
5021 return Error(IDLoc, "too few operands for instruction");
5022
Daniel Sanders52da7af2015-11-06 12:11:03 +00005023 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005024 if (ErrorLoc == SMLoc())
5025 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005026 }
5027
5028 return Error(ErrorLoc, "invalid operand for instruction");
5029 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005030 case Match_NonZeroOperandForSync:
5031 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005032 case Match_MnemonicFail:
5033 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005034 case Match_RequiresDifferentSrcAndDst:
5035 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005036 case Match_RequiresDifferentOperands:
5037 return Error(IDLoc, "registers must be different");
5038 case Match_RequiresNoZeroRegister:
5039 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005040 case Match_RequiresSameSrcAndDst:
5041 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005042 case Match_NoFCCRegisterForCurrentISA:
5043 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5044 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005045 case Match_Immz:
5046 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005047 case Match_UImm1_0:
5048 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5049 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005050 case Match_UImm2_0:
5051 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5052 "expected 2-bit unsigned immediate");
5053 case Match_UImm2_1:
5054 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5055 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005056 case Match_UImm3_0:
5057 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5058 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005059 case Match_UImm4_0:
5060 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5061 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005062 case Match_SImm4_0:
5063 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5064 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005065 case Match_UImm5_0:
5066 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5067 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005068 case Match_SImm5_0:
5069 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5070 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005071 case Match_UImm5_1:
5072 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5073 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005074 case Match_UImm5_32:
5075 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5076 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005077 case Match_UImm5_33:
5078 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5079 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005080 case Match_UImm5_0_Report_UImm6:
5081 // This is used on UImm5 operands that have a corresponding UImm5_32
5082 // operand to avoid confusing the user.
5083 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5084 "expected 6-bit unsigned immediate");
5085 case Match_UImm5_Lsl2:
5086 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5087 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005088 case Match_UImmRange2_64:
5089 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5090 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005091 case Match_UImm6_0:
5092 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5093 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005094 case Match_UImm6_Lsl2:
5095 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5096 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005097 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005098 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5099 "expected 6-bit signed immediate");
5100 case Match_UImm7_0:
5101 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5102 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005103 case Match_UImm7_N1:
5104 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5105 "expected immediate in range -1 .. 126");
5106 case Match_SImm7_Lsl2:
5107 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5108 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005109 case Match_UImm8_0:
5110 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5111 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005112 case Match_UImm10_0:
5113 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5114 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005115 case Match_SImm10_0:
5116 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5117 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005118 case Match_SImm11_0:
5119 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5120 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005121 case Match_UImm16:
5122 case Match_UImm16_Relaxed:
5123 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5124 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005125 case Match_SImm16:
5126 case Match_SImm16_Relaxed:
5127 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5128 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005129 case Match_SImm19_Lsl2:
5130 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5131 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005132 case Match_UImm20_0:
5133 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5134 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005135 case Match_UImm26_0:
5136 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5137 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005138 case Match_SImm32:
5139 case Match_SImm32_Relaxed:
5140 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5141 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005142 case Match_UImm32_Coerced:
5143 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5144 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005145 case Match_MemSImm9:
5146 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5147 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005148 case Match_MemSImm10:
5149 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5150 "expected memory with 10-bit signed offset");
5151 case Match_MemSImm10Lsl1:
5152 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5153 "expected memory with 11-bit signed offset and multiple of 2");
5154 case Match_MemSImm10Lsl2:
5155 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5156 "expected memory with 12-bit signed offset and multiple of 4");
5157 case Match_MemSImm10Lsl3:
5158 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5159 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005160 case Match_MemSImm11:
5161 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5162 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005163 case Match_MemSImm12:
5164 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5165 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005166 case Match_MemSImm16:
5167 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5168 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00005169 }
Craig Topper589ceee2015-01-03 08:16:34 +00005170
5171 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005172}
5173
Toma Tabacud9d344b2015-04-27 14:05:04 +00005174void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5175 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5176 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5177 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005178}
5179
Toma Tabacu81496c12015-05-20 08:54:45 +00005180void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5181 if (!AssemblerOptions.back()->isMacro())
5182 Warning(Loc, "macro instruction expanded into multiple instructions");
5183}
5184
Daniel Sandersef638fe2014-10-03 15:37:37 +00005185void
5186MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5187 SMRange Range, bool ShowColors) {
5188 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005189 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005190 ShowColors);
5191}
5192
Jack Carter1ac53222013-02-20 23:11:17 +00005193int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005194 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005195
Vladimir Medic4c299852013-11-06 11:27:05 +00005196 CC = StringSwitch<unsigned>(Name)
5197 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005198 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005199 .Case("a0", 4)
5200 .Case("a1", 5)
5201 .Case("a2", 6)
5202 .Case("a3", 7)
5203 .Case("v0", 2)
5204 .Case("v1", 3)
5205 .Case("s0", 16)
5206 .Case("s1", 17)
5207 .Case("s2", 18)
5208 .Case("s3", 19)
5209 .Case("s4", 20)
5210 .Case("s5", 21)
5211 .Case("s6", 22)
5212 .Case("s7", 23)
5213 .Case("k0", 26)
5214 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005215 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005216 .Case("sp", 29)
5217 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005218 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005219 .Case("ra", 31)
5220 .Case("t0", 8)
5221 .Case("t1", 9)
5222 .Case("t2", 10)
5223 .Case("t3", 11)
5224 .Case("t4", 12)
5225 .Case("t5", 13)
5226 .Case("t6", 14)
5227 .Case("t7", 15)
5228 .Case("t8", 24)
5229 .Case("t9", 25)
5230 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005231
Toma Tabacufda445c2014-09-15 15:33:01 +00005232 if (!(isABI_N32() || isABI_N64()))
5233 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005234
Daniel Sandersef638fe2014-10-03 15:37:37 +00005235 if (12 <= CC && CC <= 15) {
5236 // Name is one of t4-t7
5237 AsmToken RegTok = getLexer().peekTok();
5238 SMRange RegRange = RegTok.getLocRange();
5239
5240 StringRef FixedName = StringSwitch<StringRef>(Name)
5241 .Case("t4", "t0")
5242 .Case("t5", "t1")
5243 .Case("t6", "t2")
5244 .Case("t7", "t3")
5245 .Default("");
5246 assert(FixedName != "" && "Register name is not one of t4-t7.");
5247
5248 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5249 "Did you mean $" + FixedName + "?", RegRange);
5250 }
5251
Toma Tabacufda445c2014-09-15 15:33:01 +00005252 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5253 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5254 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5255 if (8 <= CC && CC <= 11)
5256 CC += 4;
5257
5258 if (CC == -1)
5259 CC = StringSwitch<unsigned>(Name)
5260 .Case("a4", 8)
5261 .Case("a5", 9)
5262 .Case("a6", 10)
5263 .Case("a7", 11)
5264 .Case("kt0", 26)
5265 .Case("kt1", 27)
5266 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005267
5268 return CC;
5269}
Jack Carterd0bd6422013-04-18 00:41:53 +00005270
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005271int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5272 int CC;
5273
5274 CC = StringSwitch<unsigned>(Name)
5275 .Case("hwr_cpunum", 0)
5276 .Case("hwr_synci_step", 1)
5277 .Case("hwr_cc", 2)
5278 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005279 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005280 .Default(-1);
5281
5282 return CC;
5283}
5284
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005285int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005286 if (Name[0] == 'f') {
5287 StringRef NumString = Name.substr(1);
5288 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005289 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005290 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005291 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005292 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005293 return IntVal;
5294 }
5295 return -1;
5296}
Jack Cartera63b16a2012-09-07 00:23:42 +00005297
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005298int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005299 if (Name.startswith("fcc")) {
5300 StringRef NumString = Name.substr(3);
5301 unsigned IntVal;
5302 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005303 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005304 if (IntVal > 7) // There are only 8 fcc registers.
5305 return -1;
5306 return IntVal;
5307 }
5308 return -1;
5309}
5310
5311int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005312 if (Name.startswith("ac")) {
5313 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005314 unsigned IntVal;
5315 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005316 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005317 if (IntVal > 3) // There are only 3 acc registers.
5318 return -1;
5319 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005320 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005321 return -1;
5322}
Jack Carterd0bd6422013-04-18 00:41:53 +00005323
Jack Carter5dc8ac92013-09-25 23:50:44 +00005324int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5325 unsigned IntVal;
5326
5327 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5328 return -1;
5329
5330 if (IntVal > 31)
5331 return -1;
5332
5333 return IntVal;
5334}
5335
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005336int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5337 int CC;
5338
5339 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005340 .Case("msair", 0)
5341 .Case("msacsr", 1)
5342 .Case("msaaccess", 2)
5343 .Case("msasave", 3)
5344 .Case("msamodify", 4)
5345 .Case("msarequest", 5)
5346 .Case("msamap", 6)
5347 .Case("msaunmap", 7)
5348 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005349
5350 return CC;
5351}
5352
Simon Dardis3aa8a902017-02-06 12:43:46 +00005353bool MipsAsmParser::canUseATReg() {
5354 return AssemblerOptions.back()->getATRegIndex() != 0;
5355}
5356
Toma Tabacu89a712b2015-04-15 10:48:56 +00005357unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005358 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005359 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005360 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005361 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005362 return 0;
5363 }
5364 unsigned AT = getReg(
5365 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005366 return AT;
5367}
Jack Carter0b744b32012-10-04 02:29:46 +00005368
Jack Carterd0bd6422013-04-18 00:41:53 +00005369unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005370 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005371}
5372
Toma Tabacu13964452014-09-04 13:23:44 +00005373bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005374 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005375 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005376
Jack Carter30a59822012-10-04 04:03:53 +00005377 // Check if the current operand has a custom associated parser, if so, try to
5378 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005379 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5380 if (ResTy == MatchOperand_Success)
5381 return false;
5382 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5383 // there was a match, but an error occurred, in which case, just return that
5384 // the operand parsing failed.
5385 if (ResTy == MatchOperand_ParseFail)
5386 return true;
5387
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005388 DEBUG(dbgs() << ".. Generic Parser\n");
5389
Jack Carterb4dbc172012-09-05 23:34:03 +00005390 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005391 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005392 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005393 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005394
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005395 // Almost all registers have been parsed by custom parsers. There is only
5396 // one exception to this. $zero (and it's alias $0) will reach this point
5397 // for div, divu, and similar instructions because it is not an operand
5398 // to the instruction definition but an explicit register. Special case
5399 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005400 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005401 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005402
Jack Carterd0bd6422013-04-18 00:41:53 +00005403 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005404 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005405 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005406 return true;
5407
Jack Carter873c7242013-01-12 01:03:14 +00005408 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005409 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005410 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005411 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005412 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005413
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005414 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005415 return false;
5416 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005417 default: {
5418 DEBUG(dbgs() << ".. generic integer expression\n");
5419
5420 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005421 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005422 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005423 return true;
5424
Jack Carter873c7242013-01-12 01:03:14 +00005425 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5426
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005427 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005428 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005429 }
Jack Carter0b744b32012-10-04 02:29:46 +00005430 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005431 return true;
5432}
5433
Jack Carterb5cf5902013-04-17 00:18:04 +00005434bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005435 switch (Expr->getKind()) {
5436 case MCExpr::Constant:
5437 return true;
5438 case MCExpr::SymbolRef:
5439 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
5440 case MCExpr::Binary:
5441 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
5442 if (!isEvaluated(BE->getLHS()))
5443 return false;
5444 return isEvaluated(BE->getRHS());
5445 }
5446 case MCExpr::Unary:
5447 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005448 case MCExpr::Target:
5449 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005450 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005451 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005452}
Jack Carterd0bd6422013-04-18 00:41:53 +00005453
Jack Carterb4dbc172012-09-05 23:34:03 +00005454bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5455 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005456 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005457 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005458 if (ResTy == MatchOperand_Success) {
5459 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005460 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005461 StartLoc = Operand.getStartLoc();
5462 EndLoc = Operand.getEndLoc();
5463
5464 // AFAIK, we only support numeric registers and named GPR's in CFI
5465 // directives.
5466 // Don't worry about eating tokens before failing. Using an unrecognised
5467 // register is a parse error.
5468 if (Operand.isGPRAsmReg()) {
5469 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005470 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005471 }
5472
5473 return (RegNo == (unsigned)-1);
5474 }
5475
5476 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005477 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005478}
5479
Jack Carterb5cf5902013-04-17 00:18:04 +00005480bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005481 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005482
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005483 if (isParenExpr)
5484 return getParser().parseParenExprOfDepth(0, Res, S);
5485 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005486}
5487
Alex Bradbury58eba092016-11-01 16:32:05 +00005488OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005489MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005490 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005491 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005492 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005493 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005494 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005495 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005496 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005497 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005498
Jack Carterb5cf5902013-04-17 00:18:04 +00005499 if (getLexer().getKind() == AsmToken::LParen) {
5500 Parser.Lex();
5501 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005502 }
5503
Jack Carterb5cf5902013-04-17 00:18:04 +00005504 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005505 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005506 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005507
Jack Carterd0bd6422013-04-18 00:41:53 +00005508 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005509 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005510 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005511 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005512 SMLoc E =
5513 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005514 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005515 return MatchOperand_Success;
5516 }
5517 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005518 SMLoc E =
5519 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005520
Jack Carterd0bd6422013-04-18 00:41:53 +00005521 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005522 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005523 auto Base = MipsOperand::createGPRReg(
5524 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005525 Operands.push_back(
5526 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005527 return MatchOperand_Success;
5528 }
Simon Dardis858915f2016-10-18 15:17:17 +00005529 MCBinaryExpr::Opcode Opcode;
5530 // GAS and LLVM treat comparison operators different. GAS will generate -1
5531 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5532 // highly unlikely to be found in a memory offset expression, we don't
5533 // handle them.
5534 switch (Tok.getKind()) {
5535 case AsmToken::Plus:
5536 Opcode = MCBinaryExpr::Add;
5537 Parser.Lex();
5538 break;
5539 case AsmToken::Minus:
5540 Opcode = MCBinaryExpr::Sub;
5541 Parser.Lex();
5542 break;
5543 case AsmToken::Star:
5544 Opcode = MCBinaryExpr::Mul;
5545 Parser.Lex();
5546 break;
5547 case AsmToken::Pipe:
5548 Opcode = MCBinaryExpr::Or;
5549 Parser.Lex();
5550 break;
5551 case AsmToken::Amp:
5552 Opcode = MCBinaryExpr::And;
5553 Parser.Lex();
5554 break;
5555 case AsmToken::LessLess:
5556 Opcode = MCBinaryExpr::Shl;
5557 Parser.Lex();
5558 break;
5559 case AsmToken::GreaterGreater:
5560 Opcode = MCBinaryExpr::LShr;
5561 Parser.Lex();
5562 break;
5563 case AsmToken::Caret:
5564 Opcode = MCBinaryExpr::Xor;
5565 Parser.Lex();
5566 break;
5567 case AsmToken::Slash:
5568 Opcode = MCBinaryExpr::Div;
5569 Parser.Lex();
5570 break;
5571 case AsmToken::Percent:
5572 Opcode = MCBinaryExpr::Mod;
5573 Parser.Lex();
5574 break;
5575 default:
5576 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5577 return MatchOperand_ParseFail;
5578 }
5579 const MCExpr * NextExpr;
5580 if (getParser().parseExpression(NextExpr))
5581 return MatchOperand_ParseFail;
5582 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005583 }
5584
Jack Carterd0bd6422013-04-18 00:41:53 +00005585 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005586 }
5587
Toma Tabacu13964452014-09-04 13:23:44 +00005588 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005589 if (Res != MatchOperand_Success)
5590 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005591
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005592 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005593 Error(Parser.getTok().getLoc(), "')' expected");
5594 return MatchOperand_ParseFail;
5595 }
5596
Jack Carter873c7242013-01-12 01:03:14 +00005597 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5598
Jack Carterd0bd6422013-04-18 00:41:53 +00005599 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005600
Craig Topper062a2ba2014-04-25 05:30:21 +00005601 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005602 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005603
Jack Carterd0bd6422013-04-18 00:41:53 +00005604 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005605 std::unique_ptr<MipsOperand> op(
5606 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005607 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005608 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005609 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005610 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005611 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5612 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005613 if (IdVal->evaluateAsAbsolute(Imm))
5614 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005615 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005616 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005617 getContext());
5618 }
5619
David Blaikie960ea3f2014-06-08 16:18:35 +00005620 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005621 return MatchOperand_Success;
5622}
5623
David Blaikie960ea3f2014-06-08 16:18:35 +00005624bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005625 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005626 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00005627 if (Sym) {
5628 SMLoc S = Parser.getTok().getLoc();
5629 const MCExpr *Expr;
5630 if (Sym->isVariable())
5631 Expr = Sym->getVariableValue();
5632 else
5633 return false;
5634 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005635 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005636 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005637 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005638 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005639 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005640 if (ResTy == MatchOperand_Success) {
5641 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005642 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00005643 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005644 llvm_unreachable("Should never ParseFail");
5645 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00005646 }
Jack Carterd76b2372013-03-21 21:44:16 +00005647 }
5648 }
5649 return false;
5650}
Jack Carterd0bd6422013-04-18 00:41:53 +00005651
Alex Bradbury58eba092016-11-01 16:32:05 +00005652OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005653MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00005654 StringRef Identifier,
5655 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005656 int Index = matchCPURegisterName(Identifier);
5657 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005658 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005659 Index, Identifier, getContext().getRegisterInfo(), S,
5660 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005661 return MatchOperand_Success;
5662 }
5663
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005664 Index = matchHWRegsRegisterName(Identifier);
5665 if (Index != -1) {
5666 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005667 Index, Identifier, getContext().getRegisterInfo(), S,
5668 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005669 return MatchOperand_Success;
5670 }
5671
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005672 Index = matchFPURegisterName(Identifier);
5673 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005674 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005675 Index, Identifier, getContext().getRegisterInfo(), S,
5676 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005677 return MatchOperand_Success;
5678 }
5679
5680 Index = matchFCCRegisterName(Identifier);
5681 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005682 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005683 Index, Identifier, getContext().getRegisterInfo(), S,
5684 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005685 return MatchOperand_Success;
5686 }
5687
5688 Index = matchACRegisterName(Identifier);
5689 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005690 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005691 Index, Identifier, getContext().getRegisterInfo(), S,
5692 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005693 return MatchOperand_Success;
5694 }
5695
5696 Index = matchMSA128RegisterName(Identifier);
5697 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005698 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005699 Index, Identifier, getContext().getRegisterInfo(), S,
5700 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005701 return MatchOperand_Success;
5702 }
5703
5704 Index = matchMSA128CtrlRegisterName(Identifier);
5705 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005706 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005707 Index, Identifier, getContext().getRegisterInfo(), S,
5708 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005709 return MatchOperand_Success;
5710 }
5711
5712 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00005713}
5714
Alex Bradbury58eba092016-11-01 16:32:05 +00005715OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005716MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005717 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00005718 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005719
5720 if (Token.is(AsmToken::Identifier)) {
5721 DEBUG(dbgs() << ".. identifier\n");
5722 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00005723 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005724 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00005725 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005726 } else if (Token.is(AsmToken::Integer)) {
5727 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00005728 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005729 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
5730 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005731 return MatchOperand_Success;
5732 }
5733
5734 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
5735
5736 return MatchOperand_NoMatch;
5737}
5738
Alex Bradbury58eba092016-11-01 16:32:05 +00005739OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005740MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005741 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005742 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005743
5744 auto Token = Parser.getTok();
5745
5746 SMLoc S = Token.getLoc();
5747
5748 if (Token.isNot(AsmToken::Dollar)) {
5749 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
5750 if (Token.is(AsmToken::Identifier)) {
5751 if (searchSymbolAlias(Operands))
5752 return MatchOperand_Success;
5753 }
5754 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
5755 return MatchOperand_NoMatch;
5756 }
5757 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005758
Toma Tabacu13964452014-09-04 13:23:44 +00005759 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00005760 if (ResTy == MatchOperand_Success) {
5761 Parser.Lex(); // $
5762 Parser.Lex(); // identifier
5763 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005764 return ResTy;
5765}
5766
Alex Bradbury58eba092016-11-01 16:32:05 +00005767OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005768MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005769 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005770 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005771
5772 SMLoc S = getLexer().getLoc();
5773
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005774 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005775 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005776 if (ResTy != MatchOperand_NoMatch)
5777 return ResTy;
5778
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005779 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00005780 const MCExpr *Expr = nullptr;
5781 if (Parser.parseExpression(Expr)) {
5782 // We have no way of knowing if a symbol was consumed so we must ParseFail
5783 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005784 }
Daniel Sandersffd84362014-04-01 10:41:48 +00005785 Operands.push_back(
5786 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005787 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00005788}
5789
Alex Bradbury58eba092016-11-01 16:32:05 +00005790OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005791MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005792 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00005793 const MCExpr *IdVal;
5794 // If the first token is '$' we may have register operand.
5795 if (Parser.getTok().is(AsmToken::Dollar))
5796 return MatchOperand_NoMatch;
5797 SMLoc S = Parser.getTok().getLoc();
5798 if (getParser().parseExpression(IdVal))
5799 return MatchOperand_ParseFail;
5800 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00005801 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00005802 int64_t Val = MCE->getValue();
5803 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5804 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00005805 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00005806 return MatchOperand_Success;
5807}
5808
Alex Bradbury58eba092016-11-01 16:32:05 +00005809OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005810MipsAsmParser::parseRegisterList(OperandVector &Operands) {
5811 MCAsmParser &Parser = getParser();
5812 SmallVector<unsigned, 10> Regs;
5813 unsigned RegNo;
5814 unsigned PrevReg = Mips::NoRegister;
5815 bool RegRange = false;
5816 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5817
5818 if (Parser.getTok().isNot(AsmToken::Dollar))
5819 return MatchOperand_ParseFail;
5820
5821 SMLoc S = Parser.getTok().getLoc();
5822 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
5823 SMLoc E = getLexer().getLoc();
5824 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
5825 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
5826 if (RegRange) {
5827 // Remove last register operand because registers from register range
5828 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005829 if ((isGP64bit() && RegNo == Mips::RA_64) ||
5830 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005831 Regs.push_back(RegNo);
5832 } else {
5833 unsigned TmpReg = PrevReg + 1;
5834 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005835 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
5836 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
5837 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005838 Error(E, "invalid register operand");
5839 return MatchOperand_ParseFail;
5840 }
5841
5842 PrevReg = TmpReg;
5843 Regs.push_back(TmpReg++);
5844 }
5845 }
5846
5847 RegRange = false;
5848 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005849 if ((PrevReg == Mips::NoRegister) &&
5850 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
5851 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005852 Error(E, "$16 or $31 expected");
5853 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005854 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
5855 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
5856 !isGP64bit()) ||
5857 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
5858 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
5859 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005860 Error(E, "invalid register operand");
5861 return MatchOperand_ParseFail;
5862 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005863 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
5864 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
5865 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005866 Error(E, "consecutive register numbers expected");
5867 return MatchOperand_ParseFail;
5868 }
5869
5870 Regs.push_back(RegNo);
5871 }
5872
5873 if (Parser.getTok().is(AsmToken::Minus))
5874 RegRange = true;
5875
5876 if (!Parser.getTok().isNot(AsmToken::Minus) &&
5877 !Parser.getTok().isNot(AsmToken::Comma)) {
5878 Error(E, "',' or '-' expected");
5879 return MatchOperand_ParseFail;
5880 }
5881
5882 Lex(); // Consume comma or minus
5883 if (Parser.getTok().isNot(AsmToken::Dollar))
5884 break;
5885
5886 PrevReg = RegNo;
5887 }
5888
5889 SMLoc E = Parser.getTok().getLoc();
5890 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5891 parseMemOperand(Operands);
5892 return MatchOperand_Success;
5893}
5894
Alex Bradbury58eba092016-11-01 16:32:05 +00005895OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005896MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
5897 MCAsmParser &Parser = getParser();
5898
5899 SMLoc S = Parser.getTok().getLoc();
5900 if (parseAnyRegister(Operands) != MatchOperand_Success)
5901 return MatchOperand_ParseFail;
5902
5903 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00005904 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00005905
Benjamin Kramer2b68d152016-05-09 10:31:17 +00005906 Operands.pop_back();
5907 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005908 return MatchOperand_Success;
5909}
5910
Alex Bradbury58eba092016-11-01 16:32:05 +00005911OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00005912MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
5913 MCAsmParser &Parser = getParser();
5914 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5915 SmallVector<unsigned, 10> Regs;
5916
5917 if (Parser.getTok().isNot(AsmToken::Dollar))
5918 return MatchOperand_ParseFail;
5919
5920 SMLoc S = Parser.getTok().getLoc();
5921
5922 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5923 return MatchOperand_ParseFail;
5924
5925 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5926 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5927 Regs.push_back(RegNo);
5928
5929 SMLoc E = Parser.getTok().getLoc();
5930 if (Parser.getTok().isNot(AsmToken::Comma)) {
5931 Error(E, "',' expected");
5932 return MatchOperand_ParseFail;
5933 }
5934
5935 // Remove comma.
5936 Parser.Lex();
5937
5938 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5939 return MatchOperand_ParseFail;
5940
5941 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5942 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5943 Regs.push_back(RegNo);
5944
5945 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5946
5947 return MatchOperand_Success;
5948}
5949
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005950/// Sometimes (i.e. load/stores) the operand may be followed immediately by
5951/// either this.
5952/// ::= '(', register, ')'
5953/// handle it before we iterate so we don't get tripped up by the lack of
5954/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005955bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005956 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005957 if (getLexer().is(AsmToken::LParen)) {
5958 Operands.push_back(
5959 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
5960 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005961 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005962 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005963 return Error(Loc, "unexpected token in argument list");
5964 }
5965 if (Parser.getTok().isNot(AsmToken::RParen)) {
5966 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005967 return Error(Loc, "unexpected token, expected ')'");
5968 }
5969 Operands.push_back(
5970 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
5971 Parser.Lex();
5972 }
5973 return false;
5974}
5975
5976/// Sometimes (i.e. in MSA) the operand may be followed immediately by
5977/// either one of these.
5978/// ::= '[', register, ']'
5979/// ::= '[', integer, ']'
5980/// handle it before we iterate so we don't get tripped up by the lack of
5981/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005982bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00005983 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005984 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005985 if (getLexer().is(AsmToken::LBrac)) {
5986 Operands.push_back(
5987 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
5988 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005989 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005990 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005991 return Error(Loc, "unexpected token in argument list");
5992 }
5993 if (Parser.getTok().isNot(AsmToken::RBrac)) {
5994 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005995 return Error(Loc, "unexpected token, expected ']'");
5996 }
5997 Operands.push_back(
5998 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
5999 Parser.Lex();
6000 }
6001 return false;
6002}
6003
David Blaikie960ea3f2014-06-08 16:18:35 +00006004bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6005 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006006 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006007 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006008
6009 // We have reached first instruction, module directive are now forbidden.
6010 getTargetStreamer().forbidModuleDirective();
6011
Vladimir Medic74593e62013-07-17 15:00:42 +00006012 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006013 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006014 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00006015 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006016 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006017 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006018
6019 // Read the remaining operands.
6020 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6021 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006022 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006023 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006024 return Error(Loc, "unexpected token in argument list");
6025 }
Toma Tabacu13964452014-09-04 13:23:44 +00006026 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006027 return true;
6028 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006029
Jack Carterd0bd6422013-04-18 00:41:53 +00006030 while (getLexer().is(AsmToken::Comma)) {
6031 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006032 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006033 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006034 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006035 return Error(Loc, "unexpected token in argument list");
6036 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006037 // Parse bracket and parenthesis suffixes before we iterate
6038 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006039 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006040 return true;
6041 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006042 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006043 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006044 }
6045 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006046 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6047 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006048 return Error(Loc, "unexpected token in argument list");
6049 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006050 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006051 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006052}
6053
Nirav Dave996fc132016-05-05 14:15:46 +00006054// FIXME: Given that these have the same name, these should both be
6055// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006056bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006057 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006058 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006059}
6060
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006061bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006062 return Error(Loc, ErrorMsg);
6063}
6064
Jack Carter0b744b32012-10-04 02:29:46 +00006065bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006066 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006067 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006068
6069 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006070 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006071
6072 Parser.Lex(); // Eat "noat".
6073
Jack Carterd0bd6422013-04-18 00:41:53 +00006074 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006075 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006076 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006077 return false;
6078 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006079
6080 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006081 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006082 return false;
6083}
Jack Carterd0bd6422013-04-18 00:41:53 +00006084
Jack Carter0b744b32012-10-04 02:29:46 +00006085bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006086 // Line can be: ".set at", which sets $at to $1
6087 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006088 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006089 Parser.Lex(); // Eat "at".
6090
Jack Carter0b744b32012-10-04 02:29:46 +00006091 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006092 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006093 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006094
6095 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006096 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006097 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006098 }
6099
6100 if (getLexer().isNot(AsmToken::Equal)) {
6101 reportParseError("unexpected token, expected equals sign");
6102 return false;
6103 }
6104 Parser.Lex(); // Eat "=".
6105
6106 if (getLexer().isNot(AsmToken::Dollar)) {
6107 if (getLexer().is(AsmToken::EndOfStatement)) {
6108 reportParseError("no register specified");
6109 return false;
6110 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006111 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006112 return false;
6113 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006114 }
6115 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006116
Toma Tabacu16a74492015-02-13 10:30:57 +00006117 // Find out what "reg" is.
6118 unsigned AtRegNo;
6119 const AsmToken &Reg = Parser.getTok();
6120 if (Reg.is(AsmToken::Identifier)) {
6121 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6122 } else if (Reg.is(AsmToken::Integer)) {
6123 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006124 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006125 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006126 return false;
6127 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006128
6129 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006130 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006131 reportParseError("invalid register");
6132 return false;
6133 }
6134 Parser.Lex(); // Eat "reg".
6135
6136 // If this is not the end of the statement, report an error.
6137 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6138 reportParseError("unexpected token, expected end of statement");
6139 return false;
6140 }
6141
6142 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6143
6144 Parser.Lex(); // Consume the EndOfStatement.
6145 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006146}
6147
6148bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006149 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006150 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006151 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006152 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006153 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006154 return false;
6155 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006156 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006157 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006158 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006159 return false;
6160}
6161
6162bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006163 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006164 Parser.Lex();
6165 // If this is not the end of the statement, report an error.
6166 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006167 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006168 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006169 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006170 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006171 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006172 Parser.Lex(); // Consume the EndOfStatement.
6173 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006174}
6175
6176bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006177 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006178 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006179 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006180 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006181 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006182 return false;
6183 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006184 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006185 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006186 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006187 return false;
6188}
6189
6190bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006191 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006192 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006193 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006194 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006195 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006196 return false;
6197 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006198 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006199 reportParseError("`noreorder' must be set before `nomacro'");
6200 return false;
6201 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006202 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006203 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006204 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006205 return false;
6206}
Jack Carterd76b2372013-03-21 21:44:16 +00006207
Daniel Sanders44934432014-08-07 12:03:36 +00006208bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006209 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006210 Parser.Lex();
6211
6212 // If this is not the end of the statement, report an error.
6213 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006214 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006215
6216 setFeatureBits(Mips::FeatureMSA, "msa");
6217 getTargetStreamer().emitDirectiveSetMsa();
6218 return false;
6219}
6220
6221bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006222 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006223 Parser.Lex();
6224
6225 // If this is not the end of the statement, report an error.
6226 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006227 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006228
6229 clearFeatureBits(Mips::FeatureMSA, "msa");
6230 getTargetStreamer().emitDirectiveSetNoMsa();
6231 return false;
6232}
6233
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006234bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006235 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006236 Parser.Lex(); // Eat "nodsp".
6237
6238 // If this is not the end of the statement, report an error.
6239 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6240 reportParseError("unexpected token, expected end of statement");
6241 return false;
6242 }
6243
6244 clearFeatureBits(Mips::FeatureDSP, "dsp");
6245 getTargetStreamer().emitDirectiveSetNoDsp();
6246 return false;
6247}
6248
Toma Tabacucc2502d2014-11-04 17:18:07 +00006249bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006250 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006251 Parser.Lex(); // Eat "mips16".
6252
Jack Carter39536722014-01-22 23:08:42 +00006253 // If this is not the end of the statement, report an error.
6254 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006255 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006256 return false;
6257 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006258
6259 setFeatureBits(Mips::FeatureMips16, "mips16");
6260 getTargetStreamer().emitDirectiveSetMips16();
6261 Parser.Lex(); // Consume the EndOfStatement.
6262 return false;
6263}
6264
6265bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006266 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006267 Parser.Lex(); // Eat "nomips16".
6268
6269 // If this is not the end of the statement, report an error.
6270 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6271 reportParseError("unexpected token, expected end of statement");
6272 return false;
6273 }
6274
6275 clearFeatureBits(Mips::FeatureMips16, "mips16");
6276 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006277 Parser.Lex(); // Consume the EndOfStatement.
6278 return false;
6279}
6280
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006281bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006282 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006283 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006284 // Line can be: .set fp=32
6285 // .set fp=xx
6286 // .set fp=64
6287 Parser.Lex(); // Eat fp token
6288 AsmToken Tok = Parser.getTok();
6289 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006290 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006291 return false;
6292 }
6293 Parser.Lex(); // Eat '=' token.
6294 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006295
6296 if (!parseFpABIValue(FpAbiVal, ".set"))
6297 return false;
6298
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006299 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006300 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006301 return false;
6302 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006303 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006304 Parser.Lex(); // Consume the EndOfStatement.
6305 return false;
6306}
6307
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006308bool MipsAsmParser::parseSetOddSPRegDirective() {
6309 MCAsmParser &Parser = getParser();
6310
6311 Parser.Lex(); // Eat "oddspreg".
6312 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6313 reportParseError("unexpected token, expected end of statement");
6314 return false;
6315 }
6316
6317 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6318 getTargetStreamer().emitDirectiveSetOddSPReg();
6319 return false;
6320}
6321
6322bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6323 MCAsmParser &Parser = getParser();
6324
6325 Parser.Lex(); // Eat "nooddspreg".
6326 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6327 reportParseError("unexpected token, expected end of statement");
6328 return false;
6329 }
6330
6331 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6332 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6333 return false;
6334}
6335
Toma Tabacu9db22db2014-09-09 10:15:38 +00006336bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006337 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006338 SMLoc Loc = getLexer().getLoc();
6339
6340 Parser.Lex();
6341 if (getLexer().isNot(AsmToken::EndOfStatement))
6342 return reportParseError("unexpected token, expected end of statement");
6343
6344 // Always keep an element on the options "stack" to prevent the user
6345 // from changing the initial options. This is how we remember them.
6346 if (AssemblerOptions.size() == 2)
6347 return reportParseError(Loc, ".set pop with no .set push");
6348
Akira Hatanakab11ef082015-11-14 06:35:56 +00006349 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006350 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006351 setAvailableFeatures(
6352 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6353 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006354
6355 getTargetStreamer().emitDirectiveSetPop();
6356 return false;
6357}
6358
6359bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006360 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006361 Parser.Lex();
6362 if (getLexer().isNot(AsmToken::EndOfStatement))
6363 return reportParseError("unexpected token, expected end of statement");
6364
6365 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006366 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006367 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006368
6369 getTargetStreamer().emitDirectiveSetPush();
6370 return false;
6371}
6372
Toma Tabacu29696502015-06-02 09:48:04 +00006373bool MipsAsmParser::parseSetSoftFloatDirective() {
6374 MCAsmParser &Parser = getParser();
6375 Parser.Lex();
6376 if (getLexer().isNot(AsmToken::EndOfStatement))
6377 return reportParseError("unexpected token, expected end of statement");
6378
6379 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6380 getTargetStreamer().emitDirectiveSetSoftFloat();
6381 return false;
6382}
6383
6384bool MipsAsmParser::parseSetHardFloatDirective() {
6385 MCAsmParser &Parser = getParser();
6386 Parser.Lex();
6387 if (getLexer().isNot(AsmToken::EndOfStatement))
6388 return reportParseError("unexpected token, expected end of statement");
6389
6390 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6391 getTargetStreamer().emitDirectiveSetHardFloat();
6392 return false;
6393}
6394
Jack Carterd76b2372013-03-21 21:44:16 +00006395bool MipsAsmParser::parseSetAssignment() {
6396 StringRef Name;
6397 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006398 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006399
6400 if (Parser.parseIdentifier(Name))
6401 reportParseError("expected identifier after .set");
6402
6403 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006404 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006405 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006406
Jack Carter3b2c96e2014-01-22 23:31:38 +00006407 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00006408 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00006409
Jim Grosbach6f482002015-05-18 18:43:14 +00006410 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00006411 Sym->setVariableValue(Value);
6412
6413 return false;
6414}
Jack Carterd0bd6422013-04-18 00:41:53 +00006415
Toma Tabacu26647792014-09-09 12:52:14 +00006416bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006417 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006418 Parser.Lex();
6419 if (getLexer().isNot(AsmToken::EndOfStatement))
6420 return reportParseError("unexpected token, expected end of statement");
6421
6422 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006423 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006424 setAvailableFeatures(
6425 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6426 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006427 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6428
6429 getTargetStreamer().emitDirectiveSetMips0();
6430 return false;
6431}
6432
Toma Tabacu85618b32014-08-19 14:22:52 +00006433bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006434 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006435 Parser.Lex();
6436 if (getLexer().isNot(AsmToken::Equal))
6437 return reportParseError("unexpected token, expected equals sign");
6438
6439 Parser.Lex();
6440 StringRef Arch;
6441 if (Parser.parseIdentifier(Arch))
6442 return reportParseError("expected arch identifier");
6443
6444 StringRef ArchFeatureName =
6445 StringSwitch<StringRef>(Arch)
6446 .Case("mips1", "mips1")
6447 .Case("mips2", "mips2")
6448 .Case("mips3", "mips3")
6449 .Case("mips4", "mips4")
6450 .Case("mips5", "mips5")
6451 .Case("mips32", "mips32")
6452 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006453 .Case("mips32r3", "mips32r3")
6454 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006455 .Case("mips32r6", "mips32r6")
6456 .Case("mips64", "mips64")
6457 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006458 .Case("mips64r3", "mips64r3")
6459 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006460 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006461 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006462 .Case("r4000", "mips3") // This is an implementation of Mips3.
6463 .Default("");
6464
6465 if (ArchFeatureName.empty())
6466 return reportParseError("unsupported architecture");
6467
6468 selectArch(ArchFeatureName);
6469 getTargetStreamer().emitDirectiveSetArch(Arch);
6470 return false;
6471}
6472
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006473bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006474 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006475 Parser.Lex();
6476 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006477 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006478
Matheus Almeida2852af82014-04-22 10:15:54 +00006479 switch (Feature) {
6480 default:
6481 llvm_unreachable("Unimplemented feature");
6482 case Mips::FeatureDSP:
6483 setFeatureBits(Mips::FeatureDSP, "dsp");
6484 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006485 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006486 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006487 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006488 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006489 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006490 case Mips::FeatureMips1:
6491 selectArch("mips1");
6492 getTargetStreamer().emitDirectiveSetMips1();
6493 break;
6494 case Mips::FeatureMips2:
6495 selectArch("mips2");
6496 getTargetStreamer().emitDirectiveSetMips2();
6497 break;
6498 case Mips::FeatureMips3:
6499 selectArch("mips3");
6500 getTargetStreamer().emitDirectiveSetMips3();
6501 break;
6502 case Mips::FeatureMips4:
6503 selectArch("mips4");
6504 getTargetStreamer().emitDirectiveSetMips4();
6505 break;
6506 case Mips::FeatureMips5:
6507 selectArch("mips5");
6508 getTargetStreamer().emitDirectiveSetMips5();
6509 break;
6510 case Mips::FeatureMips32:
6511 selectArch("mips32");
6512 getTargetStreamer().emitDirectiveSetMips32();
6513 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006514 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006515 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006516 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006517 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006518 case Mips::FeatureMips32r3:
6519 selectArch("mips32r3");
6520 getTargetStreamer().emitDirectiveSetMips32R3();
6521 break;
6522 case Mips::FeatureMips32r5:
6523 selectArch("mips32r5");
6524 getTargetStreamer().emitDirectiveSetMips32R5();
6525 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006526 case Mips::FeatureMips32r6:
6527 selectArch("mips32r6");
6528 getTargetStreamer().emitDirectiveSetMips32R6();
6529 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006530 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006531 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006532 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006533 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006534 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006535 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006536 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006537 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006538 case Mips::FeatureMips64r3:
6539 selectArch("mips64r3");
6540 getTargetStreamer().emitDirectiveSetMips64R3();
6541 break;
6542 case Mips::FeatureMips64r5:
6543 selectArch("mips64r5");
6544 getTargetStreamer().emitDirectiveSetMips64R5();
6545 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006546 case Mips::FeatureMips64r6:
6547 selectArch("mips64r6");
6548 getTargetStreamer().emitDirectiveSetMips64R6();
6549 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006550 }
6551 return false;
6552}
6553
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006554bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006555 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006556 if (getLexer().isNot(AsmToken::Comma)) {
6557 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006558 return Error(Loc, ErrorStr);
6559 }
6560
Matheus Almeida2852af82014-04-22 10:15:54 +00006561 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006562 return true;
6563}
6564
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006565// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
6566// In this class, it is only used for .cprestore.
6567// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
6568// MipsTargetELFStreamer and MipsAsmParser.
6569bool MipsAsmParser::isPicAndNotNxxAbi() {
6570 return inPicMode() && !(isABI_N32() || isABI_N64());
6571}
6572
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006573bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00006574 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00006575 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006576
Toma Tabacudde4c462014-11-06 10:02:45 +00006577 if (inMips16Mode()) {
6578 reportParseError(".cpload is not supported in Mips16 mode");
6579 return false;
6580 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006581
David Blaikie960ea3f2014-06-08 16:18:35 +00006582 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00006583 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006584 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6585 reportParseError("expected register containing function address");
6586 return false;
6587 }
6588
David Blaikie960ea3f2014-06-08 16:18:35 +00006589 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
6590 if (!RegOpnd.isGPRAsmReg()) {
6591 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006592 return false;
6593 }
6594
Toma Tabacudde4c462014-11-06 10:02:45 +00006595 // If this is not the end of the statement, report an error.
6596 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6597 reportParseError("unexpected token, expected end of statement");
6598 return false;
6599 }
6600
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006601 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006602 return false;
6603}
6604
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006605bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
6606 MCAsmParser &Parser = getParser();
6607
6608 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
6609 // is used in non-PIC mode.
6610
6611 if (inMips16Mode()) {
6612 reportParseError(".cprestore is not supported in Mips16 mode");
6613 return false;
6614 }
6615
6616 // Get the stack offset value.
6617 const MCExpr *StackOffset;
6618 int64_t StackOffsetVal;
6619 if (Parser.parseExpression(StackOffset)) {
6620 reportParseError("expected stack offset value");
6621 return false;
6622 }
6623
6624 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
6625 reportParseError("stack offset is not an absolute expression");
6626 return false;
6627 }
6628
6629 if (StackOffsetVal < 0) {
6630 Warning(Loc, ".cprestore with negative stack offset has no effect");
6631 IsCpRestoreSet = false;
6632 } else {
6633 IsCpRestoreSet = true;
6634 CpRestoreOffset = StackOffsetVal;
6635 }
6636
6637 // If this is not the end of the statement, report an error.
6638 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6639 reportParseError("unexpected token, expected end of statement");
6640 return false;
6641 }
6642
Daniel Sandersdf8510d2016-05-11 12:48:19 +00006643 if (!getTargetStreamer().emitDirectiveCpRestore(
6644 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00006645 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006646 Parser.Lex(); // Consume the EndOfStatement.
6647 return false;
6648}
6649
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006650bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006651 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006652 unsigned FuncReg;
6653 unsigned Save;
6654 bool SaveIsReg = true;
6655
Matheus Almeida7e815762014-06-18 13:08:59 +00006656 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006657 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006658 if (ResTy == MatchOperand_NoMatch) {
6659 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00006660 return false;
6661 }
6662
6663 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6664 if (!FuncRegOpnd.isGPRAsmReg()) {
6665 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006666 return false;
6667 }
6668
6669 FuncReg = FuncRegOpnd.getGPR32Reg();
6670 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006671
Toma Tabacu65f10572014-09-16 15:00:52 +00006672 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006673 return true;
6674
Toma Tabacu13964452014-09-04 13:23:44 +00006675 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006676 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00006677 const MCExpr *OffsetExpr;
6678 int64_t OffsetVal;
6679 SMLoc ExprLoc = getLexer().getLoc();
6680
6681 if (Parser.parseExpression(OffsetExpr) ||
6682 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
6683 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00006684 return false;
6685 }
Daniel Sanders5d796282015-09-21 09:26:55 +00006686
6687 Save = OffsetVal;
6688 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00006689 } else {
6690 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6691 if (!SaveOpnd.isGPRAsmReg()) {
6692 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006693 return false;
6694 }
6695 Save = SaveOpnd.getGPR32Reg();
6696 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006697
Toma Tabacu65f10572014-09-16 15:00:52 +00006698 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006699 return true;
6700
Toma Tabacu8874eac2015-02-18 13:46:53 +00006701 const MCExpr *Expr;
6702 if (Parser.parseExpression(Expr)) {
6703 reportParseError("expected expression");
6704 return false;
6705 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006706
Toma Tabacu8874eac2015-02-18 13:46:53 +00006707 if (Expr->getKind() != MCExpr::SymbolRef) {
6708 reportParseError("expected symbol");
6709 return false;
6710 }
6711 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
6712
Daniel Sandersf173dda2015-09-22 10:50:09 +00006713 CpSaveLocation = Save;
6714 CpSaveLocationIsRegister = SaveIsReg;
6715
Toma Tabacu8874eac2015-02-18 13:46:53 +00006716 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
6717 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006718 return false;
6719}
6720
Daniel Sandersf173dda2015-09-22 10:50:09 +00006721bool MipsAsmParser::parseDirectiveCPReturn() {
6722 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
6723 CpSaveLocationIsRegister);
6724 return false;
6725}
6726
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006727bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006728 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006729 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6730 const AsmToken &Tok = Parser.getTok();
6731
6732 if (Tok.getString() == "2008") {
6733 Parser.Lex();
6734 getTargetStreamer().emitDirectiveNaN2008();
6735 return false;
6736 } else if (Tok.getString() == "legacy") {
6737 Parser.Lex();
6738 getTargetStreamer().emitDirectiveNaNLegacy();
6739 return false;
6740 }
6741 }
6742 // If we don't recognize the option passed to the .nan
6743 // directive (e.g. no option or unknown option), emit an error.
6744 reportParseError("invalid option in .nan directive");
6745 return false;
6746}
6747
Jack Carter0b744b32012-10-04 02:29:46 +00006748bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006749 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006750 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00006751 const AsmToken &Tok = Parser.getTok();
6752
6753 if (Tok.getString() == "noat") {
6754 return parseSetNoAtDirective();
6755 } else if (Tok.getString() == "at") {
6756 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00006757 } else if (Tok.getString() == "arch") {
6758 return parseSetArchDirective();
Simon Dardisac9c30c2017-02-01 18:50:24 +00006759 } else if (Tok.getString() == "bopt") {
6760 Warning(Tok.getLoc(), "'bopt' feature is unsupported");
6761 getParser().Lex();
6762 return false;
6763 } else if (Tok.getString() == "nobopt") {
6764 // We're already running in nobopt mode, so nothing to do.
6765 getParser().Lex();
6766 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006767 } else if (Tok.getString() == "fp") {
6768 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006769 } else if (Tok.getString() == "oddspreg") {
6770 return parseSetOddSPRegDirective();
6771 } else if (Tok.getString() == "nooddspreg") {
6772 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006773 } else if (Tok.getString() == "pop") {
6774 return parseSetPopDirective();
6775 } else if (Tok.getString() == "push") {
6776 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00006777 } else if (Tok.getString() == "reorder") {
6778 return parseSetReorderDirective();
6779 } else if (Tok.getString() == "noreorder") {
6780 return parseSetNoReorderDirective();
6781 } else if (Tok.getString() == "macro") {
6782 return parseSetMacroDirective();
6783 } else if (Tok.getString() == "nomacro") {
6784 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00006785 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00006786 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006787 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00006788 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006789 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00006790 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00006791 getTargetStreamer().emitDirectiveSetNoMicroMips();
6792 Parser.eatToEndOfStatement();
6793 return false;
6794 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006795 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00006796 } else if (Tok.getString() == "mips0") {
6797 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00006798 } else if (Tok.getString() == "mips1") {
6799 return parseSetFeature(Mips::FeatureMips1);
6800 } else if (Tok.getString() == "mips2") {
6801 return parseSetFeature(Mips::FeatureMips2);
6802 } else if (Tok.getString() == "mips3") {
6803 return parseSetFeature(Mips::FeatureMips3);
6804 } else if (Tok.getString() == "mips4") {
6805 return parseSetFeature(Mips::FeatureMips4);
6806 } else if (Tok.getString() == "mips5") {
6807 return parseSetFeature(Mips::FeatureMips5);
6808 } else if (Tok.getString() == "mips32") {
6809 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00006810 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006811 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006812 } else if (Tok.getString() == "mips32r3") {
6813 return parseSetFeature(Mips::FeatureMips32r3);
6814 } else if (Tok.getString() == "mips32r5") {
6815 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006816 } else if (Tok.getString() == "mips32r6") {
6817 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006818 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006819 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006820 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006821 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006822 } else if (Tok.getString() == "mips64r3") {
6823 return parseSetFeature(Mips::FeatureMips64r3);
6824 } else if (Tok.getString() == "mips64r5") {
6825 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006826 } else if (Tok.getString() == "mips64r6") {
6827 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00006828 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006829 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006830 } else if (Tok.getString() == "nodsp") {
6831 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00006832 } else if (Tok.getString() == "msa") {
6833 return parseSetMsaDirective();
6834 } else if (Tok.getString() == "nomsa") {
6835 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00006836 } else if (Tok.getString() == "softfloat") {
6837 return parseSetSoftFloatDirective();
6838 } else if (Tok.getString() == "hardfloat") {
6839 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00006840 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00006841 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00006842 parseSetAssignment();
6843 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006844 }
Jack Carter07c818d2013-01-25 01:31:34 +00006845
Jack Carter0b744b32012-10-04 02:29:46 +00006846 return true;
6847}
6848
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006849/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00006850/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006851bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006852 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006853 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006854 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00006855 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00006856 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00006857 return true;
6858
6859 getParser().getStreamer().EmitValue(Value, Size);
6860
6861 if (getLexer().is(AsmToken::EndOfStatement))
6862 break;
6863
Jack Carter07c818d2013-01-25 01:31:34 +00006864 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006865 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00006866 Parser.Lex();
6867 }
6868 }
6869
6870 Parser.Lex();
6871 return false;
6872}
6873
Vladimir Medic4c299852013-11-06 11:27:05 +00006874/// parseDirectiveGpWord
6875/// ::= .gpword local_sym
6876bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006877 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00006878 const MCExpr *Value;
6879 // EmitGPRel32Value requires an expression, so we are using base class
6880 // method to evaluate the expression.
6881 if (getParser().parseExpression(Value))
6882 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00006883 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00006884
Vladimir Medice10c1122013-11-13 13:18:04 +00006885 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006886 return Error(getLexer().getLoc(),
6887 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00006888 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00006889 return false;
6890}
6891
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006892/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00006893/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006894bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006895 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006896 const MCExpr *Value;
6897 // EmitGPRel64Value requires an expression, so we are using base class
6898 // method to evaluate the expression.
6899 if (getParser().parseExpression(Value))
6900 return true;
6901 getParser().getStreamer().EmitGPRel64Value(Value);
6902
6903 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006904 return Error(getLexer().getLoc(),
6905 "unexpected token, expected end of statement");
6906 Parser.Lex(); // Eat EndOfStatement token.
6907 return false;
6908}
6909
6910/// parseDirectiveDtpRelWord
6911/// ::= .dtprelword tls_sym
6912bool MipsAsmParser::parseDirectiveDtpRelWord() {
6913 MCAsmParser &Parser = getParser();
6914 const MCExpr *Value;
6915 // EmitDTPRel32Value requires an expression, so we are using base class
6916 // method to evaluate the expression.
6917 if (getParser().parseExpression(Value))
6918 return true;
6919 getParser().getStreamer().EmitDTPRel32Value(Value);
6920
6921 if (getLexer().isNot(AsmToken::EndOfStatement))
6922 return Error(getLexer().getLoc(),
6923 "unexpected token, expected end of statement");
6924 Parser.Lex(); // Eat EndOfStatement token.
6925 return false;
6926}
6927
6928/// parseDirectiveDtpRelDWord
6929/// ::= .dtpreldword tls_sym
6930bool MipsAsmParser::parseDirectiveDtpRelDWord() {
6931 MCAsmParser &Parser = getParser();
6932 const MCExpr *Value;
6933 // EmitDTPRel64Value requires an expression, so we are using base class
6934 // method to evaluate the expression.
6935 if (getParser().parseExpression(Value))
6936 return true;
6937 getParser().getStreamer().EmitDTPRel64Value(Value);
6938
6939 if (getLexer().isNot(AsmToken::EndOfStatement))
6940 return Error(getLexer().getLoc(),
6941 "unexpected token, expected end of statement");
6942 Parser.Lex(); // Eat EndOfStatement token.
6943 return false;
6944}
6945
6946/// parseDirectiveTpRelWord
6947/// ::= .tprelword tls_sym
6948bool MipsAsmParser::parseDirectiveTpRelWord() {
6949 MCAsmParser &Parser = getParser();
6950 const MCExpr *Value;
6951 // EmitTPRel32Value requires an expression, so we are using base class
6952 // method to evaluate the expression.
6953 if (getParser().parseExpression(Value))
6954 return true;
6955 getParser().getStreamer().EmitTPRel32Value(Value);
6956
6957 if (getLexer().isNot(AsmToken::EndOfStatement))
6958 return Error(getLexer().getLoc(),
6959 "unexpected token, expected end of statement");
6960 Parser.Lex(); // Eat EndOfStatement token.
6961 return false;
6962}
6963
6964/// parseDirectiveTpRelDWord
6965/// ::= .tpreldword tls_sym
6966bool MipsAsmParser::parseDirectiveTpRelDWord() {
6967 MCAsmParser &Parser = getParser();
6968 const MCExpr *Value;
6969 // EmitTPRel64Value requires an expression, so we are using base class
6970 // method to evaluate the expression.
6971 if (getParser().parseExpression(Value))
6972 return true;
6973 getParser().getStreamer().EmitTPRel64Value(Value);
6974
6975 if (getLexer().isNot(AsmToken::EndOfStatement))
6976 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00006977 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00006978 Parser.Lex(); // Eat EndOfStatement token.
6979 return false;
6980}
6981
Jack Carter0cd3c192014-01-06 23:27:31 +00006982bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006983 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00006984 // Get the option token.
6985 AsmToken Tok = Parser.getTok();
6986 // At the moment only identifiers are supported.
6987 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006988 return Error(Parser.getTok().getLoc(),
6989 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00006990 }
6991
6992 StringRef Option = Tok.getIdentifier();
6993
6994 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006995 // MipsAsmParser needs to know if the current PIC mode changes.
6996 IsPicEnabled = false;
6997
Jack Carter0cd3c192014-01-06 23:27:31 +00006998 getTargetStreamer().emitDirectiveOptionPic0();
6999 Parser.Lex();
7000 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007001 return Error(Parser.getTok().getLoc(),
7002 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007003 }
7004 return false;
7005 }
7006
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007007 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007008 // MipsAsmParser needs to know if the current PIC mode changes.
7009 IsPicEnabled = true;
7010
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007011 getTargetStreamer().emitDirectiveOptionPic2();
7012 Parser.Lex();
7013 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007014 return Error(Parser.getTok().getLoc(),
7015 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007016 }
7017 return false;
7018 }
7019
Jack Carter0cd3c192014-01-06 23:27:31 +00007020 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00007021 Warning(Parser.getTok().getLoc(),
7022 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007023 Parser.eatToEndOfStatement();
7024 return false;
7025}
7026
Toma Tabacu9ca50962015-04-16 09:53:47 +00007027/// parseInsnDirective
7028/// ::= .insn
7029bool MipsAsmParser::parseInsnDirective() {
7030 // If this is not the end of the statement, report an error.
7031 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7032 reportParseError("unexpected token, expected end of statement");
7033 return false;
7034 }
7035
7036 // The actual label marking happens in
7037 // MipsELFStreamer::createPendingLabelRelocs().
7038 getTargetStreamer().emitDirectiveInsn();
7039
7040 getParser().Lex(); // Eat EndOfStatement token.
7041 return false;
7042}
7043
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007044/// parseRSectionDirective
7045/// ::= .rdata
7046bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
7047 // If this is not the end of the statement, report an error.
7048 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7049 reportParseError("unexpected token, expected end of statement");
7050 return false;
7051 }
7052
7053 MCSection *ELFSection = getContext().getELFSection(
7054 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7055 getParser().getStreamer().SwitchSection(ELFSection);
7056
7057 getParser().Lex(); // Eat EndOfStatement token.
7058 return false;
7059}
7060
Simon Atanasyanbe186202016-02-11 06:45:54 +00007061/// parseSSectionDirective
7062/// ::= .sbss
7063/// ::= .sdata
7064bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7065 // If this is not the end of the statement, report an error.
7066 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7067 reportParseError("unexpected token, expected end of statement");
7068 return false;
7069 }
7070
7071 MCSection *ELFSection = getContext().getELFSection(
7072 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7073 getParser().getStreamer().SwitchSection(ELFSection);
7074
7075 getParser().Lex(); // Eat EndOfStatement token.
7076 return false;
7077}
7078
Daniel Sanders7e527422014-07-10 13:38:23 +00007079/// parseDirectiveModule
7080/// ::= .module oddspreg
7081/// ::= .module nooddspreg
7082/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007083/// ::= .module softfloat
7084/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007085bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007086 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007087 MCAsmLexer &Lexer = getLexer();
7088 SMLoc L = Lexer.getLoc();
7089
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007090 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007091 // TODO : get a better message.
7092 reportParseError(".module directive must appear before any code");
7093 return false;
7094 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007095
Toma Tabacuc405c822015-01-23 10:40:19 +00007096 StringRef Option;
7097 if (Parser.parseIdentifier(Option)) {
7098 reportParseError("expected .module option identifier");
7099 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007100 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007101
Toma Tabacuc405c822015-01-23 10:40:19 +00007102 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007103 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007104
Toma Tabacu3c499582015-06-25 10:56:57 +00007105 // Synchronize the abiflags information with the FeatureBits information we
7106 // changed above.
7107 getTargetStreamer().updateABIInfo(*this);
7108
7109 // If printing assembly, use the recently updated abiflags information.
7110 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7111 // emitted at the end).
7112 getTargetStreamer().emitDirectiveModuleOddSPReg();
7113
Toma Tabacuc405c822015-01-23 10:40:19 +00007114 // If this is not the end of the statement, report an error.
7115 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7116 reportParseError("unexpected token, expected end of statement");
7117 return false;
7118 }
7119
7120 return false; // parseDirectiveModule has finished successfully.
7121 } else if (Option == "nooddspreg") {
7122 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007123 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007124 }
7125
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007126 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007127
Toma Tabacu3c499582015-06-25 10:56:57 +00007128 // Synchronize the abiflags information with the FeatureBits information we
7129 // changed above.
7130 getTargetStreamer().updateABIInfo(*this);
7131
7132 // If printing assembly, use the recently updated abiflags information.
7133 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7134 // emitted at the end).
7135 getTargetStreamer().emitDirectiveModuleOddSPReg();
7136
Toma Tabacuc405c822015-01-23 10:40:19 +00007137 // If this is not the end of the statement, report an error.
7138 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7139 reportParseError("unexpected token, expected end of statement");
7140 return false;
7141 }
7142
7143 return false; // parseDirectiveModule has finished successfully.
7144 } else if (Option == "fp") {
7145 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007146 } else if (Option == "softfloat") {
7147 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7148
7149 // Synchronize the ABI Flags information with the FeatureBits information we
7150 // updated above.
7151 getTargetStreamer().updateABIInfo(*this);
7152
7153 // If printing assembly, use the recently updated ABI Flags information.
7154 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7155 // emitted later).
7156 getTargetStreamer().emitDirectiveModuleSoftFloat();
7157
7158 // If this is not the end of the statement, report an error.
7159 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7160 reportParseError("unexpected token, expected end of statement");
7161 return false;
7162 }
7163
7164 return false; // parseDirectiveModule has finished successfully.
7165 } else if (Option == "hardfloat") {
7166 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7167
7168 // Synchronize the ABI Flags information with the FeatureBits information we
7169 // updated above.
7170 getTargetStreamer().updateABIInfo(*this);
7171
7172 // If printing assembly, use the recently updated ABI Flags information.
7173 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7174 // emitted later).
7175 getTargetStreamer().emitDirectiveModuleHardFloat();
7176
7177 // If this is not the end of the statement, report an error.
7178 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7179 reportParseError("unexpected token, expected end of statement");
7180 return false;
7181 }
7182
7183 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007184 } else {
7185 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7186 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007187}
7188
7189/// parseDirectiveModuleFP
7190/// ::= =32
7191/// ::= =xx
7192/// ::= =64
7193bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007194 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007195 MCAsmLexer &Lexer = getLexer();
7196
7197 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007198 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007199 return false;
7200 }
7201 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007202
Daniel Sanders7e527422014-07-10 13:38:23 +00007203 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007204 if (!parseFpABIValue(FpABI, ".module"))
7205 return false;
7206
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007207 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007208 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007209 return false;
7210 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007211
Toma Tabacua64e5402015-06-25 12:44:38 +00007212 // Synchronize the abiflags information with the FeatureBits information we
7213 // changed above.
7214 getTargetStreamer().updateABIInfo(*this);
7215
7216 // If printing assembly, use the recently updated abiflags information.
7217 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7218 // emitted at the end).
7219 getTargetStreamer().emitDirectiveModuleFP();
7220
Daniel Sanders7e527422014-07-10 13:38:23 +00007221 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007222 return false;
7223}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007224
Daniel Sanders7e527422014-07-10 13:38:23 +00007225bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007226 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007227 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007228 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007229 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007230
7231 if (Lexer.is(AsmToken::Identifier)) {
7232 StringRef Value = Parser.getTok().getString();
7233 Parser.Lex();
7234
7235 if (Value != "xx") {
7236 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7237 return false;
7238 }
7239
7240 if (!isABI_O32()) {
7241 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7242 return false;
7243 }
7244
Daniel Sanders7e527422014-07-10 13:38:23 +00007245 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007246 if (ModuleLevelOptions) {
7247 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7248 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7249 } else {
7250 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7251 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7252 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007253 return true;
7254 }
7255
7256 if (Lexer.is(AsmToken::Integer)) {
7257 unsigned Value = Parser.getTok().getIntVal();
7258 Parser.Lex();
7259
7260 if (Value != 32 && Value != 64) {
7261 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7262 return false;
7263 }
7264
7265 if (Value == 32) {
7266 if (!isABI_O32()) {
7267 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7268 return false;
7269 }
7270
Daniel Sanders7e527422014-07-10 13:38:23 +00007271 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007272 if (ModuleLevelOptions) {
7273 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7274 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7275 } else {
7276 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7277 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7278 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007279 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007280 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007281 if (ModuleLevelOptions) {
7282 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7283 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7284 } else {
7285 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7286 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7287 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007288 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007289
Daniel Sanders7e527422014-07-10 13:38:23 +00007290 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007291 }
7292
7293 return false;
7294}
7295
Jack Carter0b744b32012-10-04 02:29:46 +00007296bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007297 // This returns false if this function recognizes the directive
7298 // regardless of whether it is successfully handles or reports an
7299 // error. Otherwise it returns true to give the generic parser a
7300 // chance at recognizing it.
7301
Rafael Espindola961d4692014-11-11 05:18:41 +00007302 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007303 StringRef IDVal = DirectiveID.getString();
7304
Nirav Dave996fc132016-05-05 14:15:46 +00007305 if (IDVal == ".cpload") {
7306 parseDirectiveCpLoad(DirectiveID.getLoc());
7307 return false;
7308 }
7309 if (IDVal == ".cprestore") {
7310 parseDirectiveCpRestore(DirectiveID.getLoc());
7311 return false;
7312 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00007313 if (IDVal == ".dword") {
7314 parseDataDirective(8, DirectiveID.getLoc());
7315 return false;
7316 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007317 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007318 StringRef SymbolName;
7319
7320 if (Parser.parseIdentifier(SymbolName)) {
7321 reportParseError("expected identifier after .ent");
7322 return false;
7323 }
7324
7325 // There's an undocumented extension that allows an integer to
7326 // follow the name of the procedure which AFAICS is ignored by GAS.
7327 // Example: .ent foo,2
7328 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7329 if (getLexer().isNot(AsmToken::Comma)) {
7330 // Even though we accept this undocumented extension for compatibility
7331 // reasons, the additional integer argument does not actually change
7332 // the behaviour of the '.ent' directive, so we would like to discourage
7333 // its use. We do this by not referring to the extended version in
7334 // error messages which are not directly related to its use.
7335 reportParseError("unexpected token, expected end of statement");
7336 return false;
7337 }
7338 Parser.Lex(); // Eat the comma.
7339 const MCExpr *DummyNumber;
7340 int64_t DummyNumberVal;
7341 // If the user was explicitly trying to use the extended version,
7342 // we still give helpful extension-related error messages.
7343 if (Parser.parseExpression(DummyNumber)) {
7344 reportParseError("expected number after comma");
7345 return false;
7346 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007347 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007348 reportParseError("expected an absolute expression after comma");
7349 return false;
7350 }
7351 }
7352
7353 // If this is not the end of the statement, report an error.
7354 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7355 reportParseError("unexpected token, expected end of statement");
7356 return false;
7357 }
7358
Jim Grosbach6f482002015-05-18 18:43:14 +00007359 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007360
7361 getTargetStreamer().emitDirectiveEnt(*Sym);
7362 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007363 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007364 return false;
7365 }
7366
Jack Carter07c818d2013-01-25 01:31:34 +00007367 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007368 StringRef SymbolName;
7369
7370 if (Parser.parseIdentifier(SymbolName)) {
7371 reportParseError("expected identifier after .end");
7372 return false;
7373 }
7374
7375 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7376 reportParseError("unexpected token, expected end of statement");
7377 return false;
7378 }
7379
7380 if (CurrentFn == nullptr) {
7381 reportParseError(".end used without .ent");
7382 return false;
7383 }
7384
7385 if ((SymbolName != CurrentFn->getName())) {
7386 reportParseError(".end symbol does not match .ent symbol");
7387 return false;
7388 }
7389
7390 getTargetStreamer().emitDirectiveEnd(SymbolName);
7391 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007392 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007393 return false;
7394 }
7395
Jack Carter07c818d2013-01-25 01:31:34 +00007396 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007397 // .frame $stack_reg, frame_size_in_bytes, $return_reg
7398 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007399 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007400 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7401 reportParseError("expected stack register");
7402 return false;
7403 }
7404
7405 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7406 if (!StackRegOpnd.isGPRAsmReg()) {
7407 reportParseError(StackRegOpnd.getStartLoc(),
7408 "expected general purpose register");
7409 return false;
7410 }
7411 unsigned StackReg = StackRegOpnd.getGPR32Reg();
7412
7413 if (Parser.getTok().is(AsmToken::Comma))
7414 Parser.Lex();
7415 else {
7416 reportParseError("unexpected token, expected comma");
7417 return false;
7418 }
7419
7420 // Parse the frame size.
7421 const MCExpr *FrameSize;
7422 int64_t FrameSizeVal;
7423
7424 if (Parser.parseExpression(FrameSize)) {
7425 reportParseError("expected frame size value");
7426 return false;
7427 }
7428
Jim Grosbach13760bd2015-05-30 01:25:56 +00007429 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007430 reportParseError("frame size not an absolute expression");
7431 return false;
7432 }
7433
7434 if (Parser.getTok().is(AsmToken::Comma))
7435 Parser.Lex();
7436 else {
7437 reportParseError("unexpected token, expected comma");
7438 return false;
7439 }
7440
7441 // Parse the return register.
7442 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00007443 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007444 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7445 reportParseError("expected return register");
7446 return false;
7447 }
7448
7449 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7450 if (!ReturnRegOpnd.isGPRAsmReg()) {
7451 reportParseError(ReturnRegOpnd.getStartLoc(),
7452 "expected general purpose register");
7453 return false;
7454 }
7455
7456 // If this is not the end of the statement, report an error.
7457 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7458 reportParseError("unexpected token, expected end of statement");
7459 return false;
7460 }
7461
7462 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
7463 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007464 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007465 return false;
7466 }
7467
Jack Carter07c818d2013-01-25 01:31:34 +00007468 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00007469 parseDirectiveSet();
7470 return false;
Jack Carterbe332172012-09-07 00:48:02 +00007471 }
7472
Daniel Sandersd97a6342014-08-13 10:07:34 +00007473 if (IDVal == ".mask" || IDVal == ".fmask") {
7474 // .mask bitmask, frame_offset
7475 // bitmask: One bit for each register used.
7476 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
7477 // first register is expected to be saved.
7478 // Examples:
7479 // .mask 0x80000000, -4
7480 // .fmask 0x80000000, -4
7481 //
Jack Carterbe332172012-09-07 00:48:02 +00007482
Daniel Sandersd97a6342014-08-13 10:07:34 +00007483 // Parse the bitmask
7484 const MCExpr *BitMask;
7485 int64_t BitMaskVal;
7486
7487 if (Parser.parseExpression(BitMask)) {
7488 reportParseError("expected bitmask value");
7489 return false;
7490 }
7491
Jim Grosbach13760bd2015-05-30 01:25:56 +00007492 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007493 reportParseError("bitmask not an absolute expression");
7494 return false;
7495 }
7496
7497 if (Parser.getTok().is(AsmToken::Comma))
7498 Parser.Lex();
7499 else {
7500 reportParseError("unexpected token, expected comma");
7501 return false;
7502 }
7503
7504 // Parse the frame_offset
7505 const MCExpr *FrameOffset;
7506 int64_t FrameOffsetVal;
7507
7508 if (Parser.parseExpression(FrameOffset)) {
7509 reportParseError("expected frame offset value");
7510 return false;
7511 }
7512
Jim Grosbach13760bd2015-05-30 01:25:56 +00007513 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007514 reportParseError("frame offset not an absolute expression");
7515 return false;
7516 }
7517
7518 // If this is not the end of the statement, report an error.
7519 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7520 reportParseError("unexpected token, expected end of statement");
7521 return false;
7522 }
7523
7524 if (IDVal == ".mask")
7525 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
7526 else
7527 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00007528 return false;
7529 }
7530
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007531 if (IDVal == ".nan")
7532 return parseDirectiveNaN();
7533
Jack Carter07c818d2013-01-25 01:31:34 +00007534 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00007535 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00007536 return false;
7537 }
7538
Rafael Espindolab59fb732014-03-28 18:50:26 +00007539 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007540 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007541 return false;
7542 }
7543
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007544 if (IDVal == ".dtprelword") {
7545 parseDirectiveDtpRelWord();
7546 return false;
7547 }
7548
7549 if (IDVal == ".dtpreldword") {
7550 parseDirectiveDtpRelDWord();
7551 return false;
7552 }
7553
7554 if (IDVal == ".tprelword") {
7555 parseDirectiveTpRelWord();
7556 return false;
7557 }
7558
7559 if (IDVal == ".tpreldword") {
7560 parseDirectiveTpRelDWord();
7561 return false;
7562 }
7563
Jack Carter07c818d2013-01-25 01:31:34 +00007564 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007565 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00007566 return false;
7567 }
7568
Scott Egertond1aeb052016-02-15 16:11:51 +00007569 if (IDVal == ".hword") {
7570 parseDataDirective(2, DirectiveID.getLoc());
7571 return false;
7572 }
7573
Nirav Dave996fc132016-05-05 14:15:46 +00007574 if (IDVal == ".option") {
7575 parseDirectiveOption();
7576 return false;
7577 }
Jack Carter0cd3c192014-01-06 23:27:31 +00007578
7579 if (IDVal == ".abicalls") {
7580 getTargetStreamer().emitDirectiveAbiCalls();
7581 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007582 Error(Parser.getTok().getLoc(),
7583 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007584 }
7585 return false;
7586 }
7587
Nirav Dave996fc132016-05-05 14:15:46 +00007588 if (IDVal == ".cpsetup") {
7589 parseDirectiveCPSetup();
7590 return false;
7591 }
7592 if (IDVal == ".cpreturn") {
7593 parseDirectiveCPReturn();
7594 return false;
7595 }
7596 if (IDVal == ".module") {
7597 parseDirectiveModule();
7598 return false;
7599 }
7600 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
7601 parseInternalDirectiveReallowModule();
7602 return false;
7603 }
7604 if (IDVal == ".insn") {
7605 parseInsnDirective();
7606 return false;
7607 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007608 if (IDVal == ".rdata") {
7609 parseRSectionDirective(".rodata");
7610 return false;
7611 }
Nirav Dave996fc132016-05-05 14:15:46 +00007612 if (IDVal == ".sbss") {
7613 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
7614 return false;
7615 }
7616 if (IDVal == ".sdata") {
7617 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
7618 return false;
7619 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00007620
Rafael Espindola870c4e92012-01-11 03:56:41 +00007621 return true;
7622}
7623
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00007624bool MipsAsmParser::parseInternalDirectiveReallowModule() {
7625 // If this is not the end of the statement, report an error.
7626 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7627 reportParseError("unexpected token, expected end of statement");
7628 return false;
7629 }
7630
7631 getTargetStreamer().reallowModuleDirective();
7632
7633 getParser().Lex(); // Eat EndOfStatement token.
7634 return false;
7635}
7636
Rafael Espindola870c4e92012-01-11 03:56:41 +00007637extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00007638 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
7639 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
7640 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
7641 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00007642}
Jack Carterb4dbc172012-09-05 23:34:03 +00007643
7644#define GET_REGISTER_MATCHER
7645#define GET_MATCHER_IMPLEMENTATION
7646#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00007647
7648bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
7649 // Find the appropriate table for this asm variant.
7650 const MatchEntry *Start, *End;
7651 switch (VariantID) {
7652 default: llvm_unreachable("invalid variant!");
7653 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
7654 }
7655 // Search the table.
7656 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
7657 return MnemonicRange.first != MnemonicRange.second;
7658}