blob: e3b0635d82f2ef12b09fc0840cac0fe72cec7fdf [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
Simon Atanasyan69301c92018-05-29 15:58:06 +0000149 // Map of register aliases created via the .set directive.
150 StringMap<AsmToken> RegisterSets;
151
Daniel Sandersef638fe2014-10-03 15:37:37 +0000152 // Print a warning along with its fix-it message at the given range.
153 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
154 SMRange Range, bool ShowColors = true);
155
Simon Dardis6a319922018-05-25 16:15:48 +0000156 void ConvertXWPOperands(MCInst &Inst, const OperandVector &Operands);
157
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000158#define GET_ASSEMBLER_HEADER
159#include "MipsGenAsmMatcher.inc"
160
Daniel Sandersc5537422016-07-27 13:49:44 +0000161 unsigned
162 checkEarlyTargetMatchPredicate(MCInst &Inst,
163 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000164 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
165
Chad Rosier49963552012-10-13 00:26:04 +0000166 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000167 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000168 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000169 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000170
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000171 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000172 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000173
Toma Tabacu13964452014-09-04 13:23:44 +0000174 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000175
Toma Tabacu13964452014-09-04 13:23:44 +0000176 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000177
Craig Topper55bc6cb2017-02-08 02:54:12 +0000178 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
179
David Blaikie960ea3f2014-06-08 16:18:35 +0000180 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
181 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000182
Craig Topper56c590a2014-04-29 07:58:02 +0000183 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000184
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000185 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
186 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000187 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000188 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000189 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
Simon Atanasyan69301c92018-05-29 15:58:06 +0000190 const AsmToken &Token,
191 SMLoc S);
192 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000193 SMLoc S);
194 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
195 OperandMatchResultTy parseImm(OperandVector &Operands);
196 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
197 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000198 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
199 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
200 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000201
David Blaikie960ea3f2014-06-08 16:18:35 +0000202 bool searchSymbolAlias(OperandVector &Operands);
203
Toma Tabacu13964452014-09-04 13:23:44 +0000204 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000205
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000206 enum MacroExpanderResultTy {
207 MER_NotAMacro,
208 MER_Success,
209 MER_Fail,
210 };
Jack Carter30a59822012-10-04 04:03:53 +0000211
Matheus Almeida3813d572014-06-19 14:39:14 +0000212 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000213 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
214 MCStreamer &Out,
215 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000216
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000217 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
218 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000219
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000220 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000221 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000222 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000223
Toma Tabacuf712ede2015-06-17 14:31:51 +0000224 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
225 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000226 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000227
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000228 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
229
Toma Tabacu00e98672015-05-01 12:19:27 +0000230 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000231 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000232
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000233 bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU,
234 SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI);
236
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000237 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
238 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000239 SMLoc IDLoc, MCStreamer &Out,
240 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000241
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000242 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
243 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000244
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000245 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Simon Atanasyana1882672018-05-24 07:36:11 +0000246 const MCSubtargetInfo *STI, bool IsLoad);
Daniel Sandersfba875f2016-04-29 13:43:45 +0000247
248 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Simon Atanasyana1882672018-05-24 07:36:11 +0000249 const MCSubtargetInfo *STI);
Daniel Sandersfba875f2016-04-29 13:43:45 +0000250
251 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Simon Atanasyana1882672018-05-24 07:36:11 +0000252 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000253
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000254 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
255 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000256
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000257 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
258 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000259
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000260 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
261 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000262
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000263 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
264 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000265
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000266 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
267 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000268 const bool Signed);
269
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000270 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000271 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000272
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000273 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
274 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000275
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000276 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
277 const MCSubtargetInfo *STI);
278
279 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000280 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000281
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000282 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000283 MCStreamer &Out, const MCSubtargetInfo *STI);
284 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
285 const MCSubtargetInfo *STI);
286 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
287 const MCSubtargetInfo *STI);
288 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
289 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000290
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000291 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
292 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000293
Simon Dardis3c82a642017-02-08 16:25:05 +0000294 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
295 const MCSubtargetInfo *STI);
296
297 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
298 const MCSubtargetInfo *STI);
299
300 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
301 const MCSubtargetInfo *STI);
302
303 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
304 const MCSubtargetInfo *STI);
305
Simon Dardisaff4d142016-10-18 14:28:00 +0000306 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
307 const MCSubtargetInfo *STI, bool IsLoad);
308
Simon Dardis43115a12016-11-21 20:30:41 +0000309 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
310 const MCSubtargetInfo *STI);
311
312 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
313 const MCSubtargetInfo *STI);
314
Simon Dardisde5ed0c2017-11-14 22:26:42 +0000315 bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
316 const MCSubtargetInfo *STI);
317
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000318 bool reportParseError(Twine ErrorMsg);
319 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000320
Jack Carterb5cf5902013-04-17 00:18:04 +0000321 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000322
323 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000324 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000325 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000326 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000327 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000328 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000329 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000330 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000331 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000332 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000333 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000334 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000335 bool parseInsnDirective();
Simon Dardis1c73fcc2017-06-22 10:41:51 +0000336 bool parseRSectionDirective(StringRef Section);
Simon Atanasyanbe186202016-02-11 06:45:54 +0000337 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000338
339 bool parseSetAtDirective();
340 bool parseSetNoAtDirective();
341 bool parseSetMacroDirective();
342 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000343 bool parseSetMsaDirective();
344 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000345 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000346 bool parseSetReorderDirective();
347 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000348 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000349 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000350 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000351 bool parseSetOddSPRegDirective();
352 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000353 bool parseSetPopDirective();
354 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000355 bool parseSetSoftFloatDirective();
356 bool parseSetHardFloatDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +0000357 bool parseSetMtDirective();
358 bool parseSetNoMtDirective();
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000359 bool parseSetNoCRCDirective();
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000360 bool parseSetNoVirtDirective();
Petar Jovanovicdaf51692018-05-17 16:30:32 +0000361 bool parseSetNoGINVDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000362
Jack Carterd76b2372013-03-21 21:44:16 +0000363 bool parseSetAssignment();
364
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000365 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000366 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000367 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000368 bool parseDirectiveDtpRelWord();
369 bool parseDirectiveDtpRelDWord();
370 bool parseDirectiveTpRelWord();
371 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000372 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000373 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000374 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
375 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000376
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000377 bool parseInternalDirectiveReallowModule();
378
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000379 bool eatComma(StringRef ErrorStr);
380
Jack Carter1ac53222013-02-20 23:11:17 +0000381 int matchCPURegisterName(StringRef Symbol);
382
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000383 int matchHWRegsRegisterName(StringRef Symbol);
384
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000385 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000386
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000387 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000388
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000389 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000390
Jack Carter5dc8ac92013-09-25 23:50:44 +0000391 int matchMSA128RegisterName(StringRef Name);
392
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000393 int matchMSA128CtrlRegisterName(StringRef Name);
394
Jack Carterd0bd6422013-04-18 00:41:53 +0000395 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000396
Toma Tabacu89a712b2015-04-15 10:48:56 +0000397 /// Returns the internal register number for the current AT. Also checks if
398 /// the current AT is unavailable (set to $0) and gives an error if it is.
399 /// This should be used in pseudo-instruction expansions which need AT.
400 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000401
Simon Dardis3aa8a902017-02-06 12:43:46 +0000402 bool canUseATReg();
403
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000404 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
405 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000406
407 // Helper function that checks if the value of a vector index is within the
408 // boundaries of accepted values for each RegisterKind
409 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
410 bool validateMSAIndex(int Val, int RegKind);
411
Daniel Sandersf0df2212014-08-04 12:20:00 +0000412 // Selects a new architecture by updating the FeatureBits with the necessary
413 // info including implied dependencies.
414 // Internally, it clears all the feature bits related to *any* architecture
415 // and selects the new one using the ToggleFeature functionality of the
416 // MCSubtargetInfo object that handles implied dependencies. The reason we
417 // clear all the arch related bits manually is because ToggleFeature only
418 // clears the features that imply the feature being cleared and not the
419 // features implied by the feature being cleared. This is easier to see
420 // with an example:
421 // --------------------------------------------------
422 // | Feature | Implies |
423 // | -------------------------------------------------|
424 // | FeatureMips1 | None |
425 // | FeatureMips2 | FeatureMips1 |
426 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
427 // | FeatureMips4 | FeatureMips3 |
428 // | ... | |
429 // --------------------------------------------------
430 //
431 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
432 // FeatureMipsGP64 | FeatureMips1)
433 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
434 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000435 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000436 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000437 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
438 STI.setFeatureBits(FeatureBits);
439 setAvailableFeatures(
440 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000441 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000442 }
443
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000444 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000445 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000446 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000447 setAvailableFeatures(
448 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000449 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000450 }
451 }
452
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000453 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000454 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000455 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000456 setAvailableFeatures(
457 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000458 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000459 }
460 }
461
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000462 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
463 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000464 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000465 }
466
467 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
468 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000469 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000470 }
471
Rafael Espindola870c4e92012-01-11 03:56:41 +0000472public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000473 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000474 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000475 Match_RequiresDifferentOperands,
476 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000477 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000478 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000479 Match_NonZeroOperandForSync,
Simon Dardis52ae4f02018-03-07 11:39:48 +0000480 Match_NonZeroOperandForMTCX,
Simon Dardis6f83ae32017-09-14 15:17:50 +0000481 Match_RequiresPosSizeRange0_32,
482 Match_RequiresPosSizeRange33_64,
Simon Dardis55e44672017-09-14 17:27:53 +0000483 Match_RequiresPosSizeUImm6,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000484#define GET_OPERAND_DIAGNOSTIC_TYPES
485#include "MipsGenAsmMatcher.inc"
486#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000487 };
488
Akira Hatanakab11ef082015-11-14 06:35:56 +0000489 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000490 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000491 : MCTargetAsmParser(Options, sti, MII),
Daniel Sanders50f17232015-09-15 16:17:27 +0000492 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
493 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000494 MCAsmParserExtension::Initialize(parser);
495
Toma Tabacu11e14a92015-04-21 11:50:52 +0000496 parser.addAliasForDirective(".asciiz", ".asciz");
497
Jack Carterb4dbc172012-09-05 23:34:03 +0000498 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000500
Toma Tabacu9db22db2014-09-09 10:15:38 +0000501 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000502 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000503 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000504
Toma Tabacu9db22db2014-09-09 10:15:38 +0000505 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000506 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000507 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000508
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000509 getTargetStreamer().updateABIInfo(*this);
510
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000511 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000512 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000513
514 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000515
Rafael Espindola699281c2016-05-18 11:58:50 +0000516 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000517
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000518 IsCpRestoreSet = false;
519 CpRestoreOffset = -1;
520
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000521 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000522 if ((TheTriple.getArch() == Triple::mips) ||
523 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000524 IsLittleEndian = false;
525 else
526 IsLittleEndian = true;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +0000527
528 if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
529 report_fatal_error("microMIPS64R6 is not supported", false);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000530 }
531
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000532 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
533 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
534
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000535 bool isGP64bit() const {
536 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
537 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000538
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000539 bool isFP64bit() const {
540 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
541 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000542
Eric Christophera5762812015-01-26 17:33:46 +0000543 const MipsABIInfo &getABI() const { return ABI; }
544 bool isABI_N32() const { return ABI.IsN32(); }
545 bool isABI_N64() const { return ABI.IsN64(); }
546 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000547 bool isABI_FPXX() const {
548 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
549 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000550
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000551 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000552 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000553 }
554
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000555 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000556 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000557 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000558
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000559 bool hasMips1() const {
560 return getSTI().getFeatureBits()[Mips::FeatureMips1];
561 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000562
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000563 bool hasMips2() const {
564 return getSTI().getFeatureBits()[Mips::FeatureMips2];
565 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000566
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000567 bool hasMips3() const {
568 return getSTI().getFeatureBits()[Mips::FeatureMips3];
569 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000570
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000571 bool hasMips4() const {
572 return getSTI().getFeatureBits()[Mips::FeatureMips4];
573 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000574
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000575 bool hasMips5() const {
576 return getSTI().getFeatureBits()[Mips::FeatureMips5];
577 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000578
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000579 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000580 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000581 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000582
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000583 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000584 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000585 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000586
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000587 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000588 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000589 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000590
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000591 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000592 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000593 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000594
Daniel Sanders17793142015-02-18 16:24:50 +0000595 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000596 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000597 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000598
Daniel Sanders17793142015-02-18 16:24:50 +0000599 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000600 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000601 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000602
Daniel Sanders17793142015-02-18 16:24:50 +0000603 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000604 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000605 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000606
Daniel Sanders17793142015-02-18 16:24:50 +0000607 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000608 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000609 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000610
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000611 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000612 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000613 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000614
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000615 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000616 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000617 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000618
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000619 bool hasDSP() const {
620 return getSTI().getFeatureBits()[Mips::FeatureDSP];
621 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000622
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000623 bool hasDSPR2() const {
624 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
625 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000626
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000627 bool hasDSPR3() const {
628 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
629 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000630
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000631 bool hasMSA() const {
632 return getSTI().getFeatureBits()[Mips::FeatureMSA];
633 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000634
Kai Nackee0245392015-01-27 19:11:28 +0000635 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000636 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000637 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000638
Daniel Sandersa6994442015-08-18 12:33:54 +0000639 bool inPicMode() {
640 return IsPicEnabled;
641 }
642
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000643 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000644 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000645 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000646
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000647 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000648 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000649 }
650
Eric Christophere8ae3e32015-05-07 23:10:21 +0000651 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000652 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000653 }
Simon Dardisae719c52017-07-11 18:03:20 +0000654 bool hasMT() const {
655 return getSTI().getFeatureBits()[Mips::FeatureMT];
656 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000657
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000658 bool hasCRC() const {
659 return getSTI().getFeatureBits()[Mips::FeatureCRC];
660 }
661
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000662 bool hasVirt() const {
663 return getSTI().getFeatureBits()[Mips::FeatureVirt];
664 }
665
Petar Jovanovicdaf51692018-05-17 16:30:32 +0000666 bool hasGINV() const {
667 return getSTI().getFeatureBits()[Mips::FeatureGINV];
668 }
669
Toma Tabacud9d344b2015-04-27 14:05:04 +0000670 /// Warn if RegIndex is the same as the current AT.
671 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000672
673 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000674
675 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000676
677 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
678 AsmToken::TokenKind OperatorToken,
679 MCContext &Ctx) override {
680 switch(OperatorToken) {
681 default:
682 llvm_unreachable("Unknown token");
683 return nullptr;
684 case AsmToken::PercentCall16:
685 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
686 case AsmToken::PercentCall_Hi:
687 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
688 case AsmToken::PercentCall_Lo:
689 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
690 case AsmToken::PercentDtprel_Hi:
691 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
692 case AsmToken::PercentDtprel_Lo:
693 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
694 case AsmToken::PercentGot:
695 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
696 case AsmToken::PercentGot_Disp:
697 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
698 case AsmToken::PercentGot_Hi:
699 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
700 case AsmToken::PercentGot_Lo:
701 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
702 case AsmToken::PercentGot_Ofst:
703 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
704 case AsmToken::PercentGot_Page:
705 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
706 case AsmToken::PercentGottprel:
707 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
708 case AsmToken::PercentGp_Rel:
709 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
710 case AsmToken::PercentHi:
711 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
712 case AsmToken::PercentHigher:
713 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
714 case AsmToken::PercentHighest:
715 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
716 case AsmToken::PercentLo:
717 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
718 case AsmToken::PercentNeg:
719 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
720 case AsmToken::PercentPcrel_Hi:
721 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
722 case AsmToken::PercentPcrel_Lo:
723 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
724 case AsmToken::PercentTlsgd:
725 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
726 case AsmToken::PercentTlsldm:
727 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
728 case AsmToken::PercentTprel_Hi:
729 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
730 case AsmToken::PercentTprel_Lo:
731 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
732 }
733 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000734};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000735
736/// MipsOperand - Instances of this class represent a parsed Mips machine
737/// instruction.
738class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000739public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000740 /// Broad categories of register classes
741 /// The exact class is finalized by the render method.
742 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000743 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000744 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000745 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000746 RegKind_FCC = 4, /// FCC
747 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
748 RegKind_MSACtrl = 16, /// MSA control registers
749 RegKind_COP2 = 32, /// COP2
750 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
751 /// context).
752 RegKind_CCR = 128, /// CCR
753 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000754 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000755 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000756 /// Potentially any (e.g. $1)
757 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
758 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000759 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000760 };
761
762private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000763 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000764 k_Immediate, /// An immediate (possibly involving symbol references)
765 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000766 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000767 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000768 k_RegList, /// A physical register list
769 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000770 } Kind;
771
David Blaikie960ea3f2014-06-08 16:18:35 +0000772public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000773 MipsOperand(KindTy K, MipsAsmParser &Parser)
774 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
775
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000776 ~MipsOperand() override {
777 switch (Kind) {
778 case k_Immediate:
779 break;
780 case k_Memory:
781 delete Mem.Base;
782 break;
783 case k_RegList:
784 delete RegList.List;
785 case k_RegisterIndex:
786 case k_Token:
787 case k_RegPair:
788 break;
789 }
790 }
791
David Blaikie960ea3f2014-06-08 16:18:35 +0000792private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000793 /// For diagnostics, and checking the assembler temporary
794 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000795
Eric Christopher8996c5d2013-03-15 00:42:55 +0000796 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000797 const char *Data;
798 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000799 };
800
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000801 struct RegIdxOp {
802 unsigned Index; /// Index into the register class
803 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000804 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000806 };
807
808 struct ImmOp {
809 const MCExpr *Val;
810 };
811
812 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000813 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000814 const MCExpr *Off;
815 };
816
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000817 struct RegListOp {
818 SmallVector<unsigned, 10> *List;
819 };
820
Jack Carterb4dbc172012-09-05 23:34:03 +0000821 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000822 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000823 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000824 struct ImmOp Imm;
825 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000826 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000827 };
828
829 SMLoc StartLoc, EndLoc;
830
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000831 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000832 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
833 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000834 const MCRegisterInfo *RegInfo,
835 SMLoc S, SMLoc E,
836 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000837 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000838 Op->RegIdx.Index = Index;
839 Op->RegIdx.RegInfo = RegInfo;
840 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000841 Op->RegIdx.Tok.Data = Str.data();
842 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000843 Op->StartLoc = S;
844 Op->EndLoc = E;
845 return Op;
846 }
847
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000848public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000849 /// Coerce the register to GPR32 and return the real register for the current
850 /// target.
851 unsigned getGPR32Reg() const {
852 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000853 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000854 unsigned ClassID = Mips::GPR32RegClassID;
855 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000856 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000857
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000858 /// Coerce the register to GPR32 and return the real register for the current
859 /// target.
860 unsigned getGPRMM16Reg() const {
861 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
862 unsigned ClassID = Mips::GPR32RegClassID;
863 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
864 }
865
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000866 /// Coerce the register to GPR64 and return the real register for the current
867 /// target.
868 unsigned getGPR64Reg() const {
869 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
870 unsigned ClassID = Mips::GPR64RegClassID;
871 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000872 }
873
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000874private:
875 /// Coerce the register to AFGR64 and return the real register for the current
876 /// target.
877 unsigned getAFGR64Reg() const {
878 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
879 if (RegIdx.Index % 2 != 0)
880 AsmParser.Warning(StartLoc, "Float register should be even.");
881 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
882 .getRegister(RegIdx.Index / 2);
883 }
884
885 /// Coerce the register to FGR64 and return the real register for the current
886 /// target.
887 unsigned getFGR64Reg() const {
888 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
889 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
890 .getRegister(RegIdx.Index);
891 }
892
893 /// Coerce the register to FGR32 and return the real register for the current
894 /// target.
895 unsigned getFGR32Reg() const {
896 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
897 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
898 .getRegister(RegIdx.Index);
899 }
900
901 /// Coerce the register to FGRH32 and return the real register for the current
902 /// target.
903 unsigned getFGRH32Reg() const {
904 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
905 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
906 .getRegister(RegIdx.Index);
907 }
908
909 /// Coerce the register to FCC and return the real register for the current
910 /// target.
911 unsigned getFCCReg() const {
912 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
913 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
914 .getRegister(RegIdx.Index);
915 }
916
917 /// Coerce the register to MSA128 and return the real register for the current
918 /// target.
919 unsigned getMSA128Reg() const {
920 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
921 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
922 // identical
923 unsigned ClassID = Mips::MSA128BRegClassID;
924 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
925 }
926
927 /// Coerce the register to MSACtrl and return the real register for the
928 /// current target.
929 unsigned getMSACtrlReg() const {
930 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
931 unsigned ClassID = Mips::MSACtrlRegClassID;
932 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
933 }
934
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000935 /// Coerce the register to COP0 and return the real register for the
936 /// current target.
937 unsigned getCOP0Reg() const {
938 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
939 unsigned ClassID = Mips::COP0RegClassID;
940 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
941 }
942
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000943 /// Coerce the register to COP2 and return the real register for the
944 /// current target.
945 unsigned getCOP2Reg() const {
946 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
947 unsigned ClassID = Mips::COP2RegClassID;
948 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
949 }
950
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000951 /// Coerce the register to COP3 and return the real register for the
952 /// current target.
953 unsigned getCOP3Reg() const {
954 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
955 unsigned ClassID = Mips::COP3RegClassID;
956 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
957 }
958
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000959 /// Coerce the register to ACC64DSP and return the real register for the
960 /// current target.
961 unsigned getACC64DSPReg() const {
962 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
963 unsigned ClassID = Mips::ACC64DSPRegClassID;
964 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
965 }
966
967 /// Coerce the register to HI32DSP and return the real register for the
968 /// current target.
969 unsigned getHI32DSPReg() const {
970 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
971 unsigned ClassID = Mips::HI32DSPRegClassID;
972 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
973 }
974
975 /// Coerce the register to LO32DSP and return the real register for the
976 /// current target.
977 unsigned getLO32DSPReg() const {
978 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
979 unsigned ClassID = Mips::LO32DSPRegClassID;
980 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
981 }
982
983 /// Coerce the register to CCR and return the real register for the
984 /// current target.
985 unsigned getCCRReg() const {
986 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
987 unsigned ClassID = Mips::CCRRegClassID;
988 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
989 }
990
991 /// Coerce the register to HWRegs and return the real register for the
992 /// current target.
993 unsigned getHWRegsReg() const {
994 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
995 unsigned ClassID = Mips::HWRegsRegClassID;
996 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
997 }
998
999public:
Vladimir Medic4c299852013-11-06 11:27:05 +00001000 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001001 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +00001002 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001003 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +00001004 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001005 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +00001006 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001007 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001008 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001009
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001010 void addRegOperands(MCInst &Inst, unsigned N) const {
1011 llvm_unreachable("Use a custom parser instead");
1012 }
1013
Daniel Sanders21bce302014-04-01 12:35:23 +00001014 /// Render the operand to an MCInst as a GPR32
1015 /// Asserts if the wrong number of operands are requested, or the operand
1016 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +00001017 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1018 assert(N == 1 && "Invalid number of operands!");
1019 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1020 }
1021
1022 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1023 assert(N == 1 && "Invalid number of operands!");
1024 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1025 }
1026
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001027 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1028 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001029 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001030 }
1031
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001032 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
1033 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001034 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001035 }
1036
Jozef Kolek1904fa22014-11-24 14:25:53 +00001037 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1038 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001039 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001040 }
1041
Zoran Jovanovic41688672015-02-10 16:36:20 +00001042 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1043 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001044 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001045 }
1046
Daniel Sanders21bce302014-04-01 12:35:23 +00001047 /// Render the operand to an MCInst as a GPR64
1048 /// Asserts if the wrong number of operands are requested, or the operand
1049 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001050 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1051 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001052 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001053 }
1054
1055 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1056 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001057 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001058 }
1059
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001060 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1061 assert(N == 1 && "Invalid number of operands!");
1062 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1063 }
1064
1065 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1066 assert(N == 1 && "Invalid number of operands!");
1067 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1068 }
1069
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001070 void addFGR64AsmRegOperands(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(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001073 }
1074
1075 void addFGR32AsmRegOperands(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(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001078 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001079 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001080 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001081 AsmParser.getParser().printError(
1082 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1083 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001084 }
1085
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001086 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1087 assert(N == 1 && "Invalid number of operands!");
1088 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1089 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1090 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1091 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1092 "registers");
1093 }
1094
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001095 void addFGRH32AsmRegOperands(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(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001098 }
1099
1100 void addFCCAsmRegOperands(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(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001103 }
1104
1105 void addMSA128AsmRegOperands(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(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 }
1109
1110 void addMSACtrlAsmRegOperands(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(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001113 }
1114
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001115 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1116 assert(N == 1 && "Invalid number of operands!");
1117 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1118 }
1119
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001120 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1121 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001122 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001123 }
1124
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001125 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1126 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001127 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001128 }
1129
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001130 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1131 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001132 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001133 }
1134
1135 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1136 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001137 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001138 }
1139
1140 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1141 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001142 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001143 }
1144
1145 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1146 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001147 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001148 }
1149
1150 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1151 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001152 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001153 }
1154
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001155 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001156 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1157 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001158 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001159 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001160 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001161 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001162 Inst.addOperand(MCOperand::createImm(Imm));
1163 }
1164
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001165 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001166 void addSImmOperands(MCInst &Inst, unsigned N) const {
1167 if (isImm() && !isConstantImm()) {
1168 addExpr(Inst, getImm());
1169 return;
1170 }
1171 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1172 }
1173
1174 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001175 void addUImmOperands(MCInst &Inst, unsigned N) const {
1176 if (isImm() && !isConstantImm()) {
1177 addExpr(Inst, getImm());
1178 return;
1179 }
1180 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1181 }
1182
Daniel Sanders78e89022016-03-11 11:37:50 +00001183 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1184 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1185 assert(N == 1 && "Invalid number of operands!");
1186 int64_t Imm = getConstantImm() - Offset;
1187 Imm = SignExtend64<Bits>(Imm);
1188 Imm += Offset;
1189 Imm += AdjustOffset;
1190 Inst.addOperand(MCOperand::createImm(Imm));
1191 }
1192
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001193 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001194 assert(N == 1 && "Invalid number of operands!");
1195 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001196 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001197 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001198
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001199 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001200 assert(N == 2 && "Invalid number of operands!");
1201
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001202 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1203 ? getMemBase()->getGPR64Reg()
1204 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001205
1206 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001207 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001208 }
1209
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001210 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1211 assert(N == 2 && "Invalid number of operands!");
1212
Jim Grosbache9119e42015-05-13 18:37:00 +00001213 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001214
1215 const MCExpr *Expr = getMemOff();
1216 addExpr(Inst, Expr);
1217 }
1218
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001219 void addRegListOperands(MCInst &Inst, unsigned N) const {
1220 assert(N == 1 && "Invalid number of operands!");
1221
1222 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001223 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001224 }
1225
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001226 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1227 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001228 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001229 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001230 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1231 Inst.addOperand(MCOperand::createReg(
1232 RegIdx.RegInfo->getRegClass(
1233 AsmParser.getABI().AreGprs64bit()
1234 ? Mips::GPR64RegClassID
1235 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1236 Inst.addOperand(MCOperand::createReg(
1237 RegIdx.RegInfo->getRegClass(
1238 AsmParser.getABI().AreGprs64bit()
1239 ? Mips::GPR64RegClassID
1240 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001241 }
1242
Zoran Jovanovic41688672015-02-10 16:36:20 +00001243 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1244 assert(N == 2 && "Invalid number of operands!");
1245 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001246 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001247 }
1248
Craig Topper56c590a2014-04-29 07:58:02 +00001249 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001250 // As a special case until we sort out the definition of div/divu, accept
1251 // $0/$zero here so that MCK_ZERO works correctly.
1252 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001253 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001254
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001255 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001256 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001257
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001258 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001259 int64_t Res;
1260 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001261 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001262
Daniel Sanders52da7af2015-11-06 12:11:03 +00001263 bool isConstantImmz() const {
1264 return isConstantImm() && getConstantImm() == 0;
1265 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001266
Daniel Sandersea4f6532015-11-06 12:22:31 +00001267 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1268 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1269 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001270
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001271 template <unsigned Bits> bool isSImm() const {
1272 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1273 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001274
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001275 template <unsigned Bits> bool isUImm() const {
1276 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1277 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001278
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001279 template <unsigned Bits> bool isAnyImm() const {
1280 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1281 isUInt<Bits>(getConstantImm()))
1282 : isImm();
1283 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001284
Daniel Sanders78e89022016-03-11 11:37:50 +00001285 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1286 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001287 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001288
Hrvoje Varga46458d02016-02-25 12:53:29 +00001289 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1290 return isConstantImm() && getConstantImm() >= Bottom &&
1291 getConstantImm() <= Top;
1292 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001293
Craig Topper56c590a2014-04-29 07:58:02 +00001294 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001295 // Note: It's not possible to pretend that other operand kinds are tokens.
1296 // The matcher emitter checks tokens first.
1297 return Kind == k_Token;
1298 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001299
Craig Topper56c590a2014-04-29 07:58:02 +00001300 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001301
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001302 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001303 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001304 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001305
Simon Dardis4ccda502016-05-27 13:56:36 +00001306 // Allow relocation operators.
1307 // FIXME: This predicate and others need to look through binary expressions
1308 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001309 template <unsigned Bits, unsigned ShiftAmount = 0>
1310 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001311 if (!isMem())
1312 return false;
1313 if (!getMemBase()->isGPRAsmReg())
1314 return false;
1315 if (isa<MCTargetExpr>(getMemOff()) ||
1316 (isConstantMemOff() &&
1317 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1318 return true;
1319 MCValue Res;
1320 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1321 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001322 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001323
Simon Atanasyand4d892f2018-04-26 19:55:28 +00001324 bool isMemWithPtrSizeOffset() const {
1325 if (!isMem())
1326 return false;
1327 if (!getMemBase()->isGPRAsmReg())
1328 return false;
1329 const unsigned PtrBits = 32;
1330 if (isa<MCTargetExpr>(getMemOff()) ||
1331 (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))
1332 return true;
1333 MCValue Res;
1334 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1335 return IsReloc && isIntN(PtrBits, Res.getConstant());
1336 }
1337
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001338 bool isMemWithGRPMM16Base() const {
1339 return isMem() && getMemBase()->isMM16AsmReg();
1340 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001341
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001342 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1343 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1344 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1345 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001346
Jozef Kolek12c69822014-12-23 16:16:33 +00001347 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1348 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1349 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1350 && (getMemBase()->getGPR32Reg() == Mips::SP);
1351 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001352
Daniel Sanderse473dc92016-05-09 13:38:25 +00001353 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1354 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1355 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1356 && (getMemBase()->getGPR32Reg() == Mips::GP);
1357 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001358
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001359 template <unsigned Bits, unsigned ShiftLeftAmount>
1360 bool isScaledUImm() const {
1361 return isConstantImm() &&
1362 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001363 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001364
Daniel Sanders97297772016-03-22 14:40:00 +00001365 template <unsigned Bits, unsigned ShiftLeftAmount>
1366 bool isScaledSImm() const {
Simon Atanasyan478220f2018-05-24 07:36:00 +00001367 if (isConstantImm() &&
1368 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001369 return true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00001370 // Operand can also be a symbol or symbol plus
1371 // offset in case of relocations.
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001372 if (Kind != k_Immediate)
1373 return false;
1374 MCValue Res;
1375 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1376 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001377 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001378
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001379 bool isRegList16() const {
1380 if (!isRegList())
1381 return false;
1382
1383 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001384 if (Size < 2 || Size > 5)
1385 return false;
1386
1387 unsigned R0 = RegList.List->front();
1388 unsigned R1 = RegList.List->back();
1389 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1390 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001391 return false;
1392
1393 int PrevReg = *RegList.List->begin();
1394 for (int i = 1; i < Size - 1; i++) {
1395 int Reg = (*(RegList.List))[i];
1396 if ( Reg != PrevReg + 1)
1397 return false;
1398 PrevReg = Reg;
1399 }
1400
1401 return true;
1402 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001403
Vladimir Medic2b953d02013-10-01 09:48:56 +00001404 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001405
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001406 bool isLSAImm() const {
1407 if (!isConstantImm())
1408 return false;
1409 int64_t Val = getConstantImm();
1410 return 1 <= Val && Val <= 4;
1411 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001412
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001413 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001414
Zoran Jovanovic41688672015-02-10 16:36:20 +00001415 bool isMovePRegPair() const {
1416 if (Kind != k_RegList || RegList.List->size() != 2)
1417 return false;
1418
1419 unsigned R0 = RegList.List->front();
1420 unsigned R1 = RegList.List->back();
1421
1422 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1423 (R0 == Mips::A1 && R1 == Mips::A3) ||
1424 (R0 == Mips::A2 && R1 == Mips::A3) ||
1425 (R0 == Mips::A0 && R1 == Mips::S5) ||
1426 (R0 == Mips::A0 && R1 == Mips::S6) ||
1427 (R0 == Mips::A0 && R1 == Mips::A1) ||
1428 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001429 (R0 == Mips::A0 && R1 == Mips::A3) ||
1430 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1431 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1432 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1433 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1434 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1435 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1436 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1437 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001438 return true;
1439
1440 return false;
1441 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001442
1443 StringRef getToken() const {
1444 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001445 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001446 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001447
Zlatko Buljanba553a62016-05-09 08:07:28 +00001448 bool isRegPair() const {
1449 return Kind == k_RegPair && RegIdx.Index <= 30;
1450 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001451
Craig Topper56c590a2014-04-29 07:58:02 +00001452 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001453 // As a special case until we sort out the definition of div/divu, accept
1454 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001455 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1456 RegIdx.Kind & RegKind_GPR)
1457 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001458
Daniel Sanders976d9382016-07-05 13:38:40 +00001459 llvm_unreachable("Invalid access!");
1460 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001461 }
1462
Jack Carterb4dbc172012-09-05 23:34:03 +00001463 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001464 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001465 return Imm.Val;
1466 }
1467
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001468 int64_t getConstantImm() const {
1469 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001470 int64_t Value = 0;
1471 (void)Val->evaluateAsAbsolute(Value);
1472 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001473 }
1474
1475 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001476 assert((Kind == k_Memory) && "Invalid access!");
1477 return Mem.Base;
1478 }
1479
1480 const MCExpr *getMemOff() const {
1481 assert((Kind == k_Memory) && "Invalid access!");
1482 return Mem.Off;
1483 }
1484
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001485 int64_t getConstantMemOff() const {
1486 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1487 }
1488
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001489 const SmallVectorImpl<unsigned> &getRegList() const {
1490 assert((Kind == k_RegList) && "Invalid access!");
1491 return *(RegList.List);
1492 }
1493
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001494 unsigned getRegPair() const {
1495 assert((Kind == k_RegPair) && "Invalid access!");
1496 return RegIdx.Index;
1497 }
1498
David Blaikie960ea3f2014-06-08 16:18:35 +00001499 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1500 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001501 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001502 Op->Tok.Data = Str.data();
1503 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001504 Op->StartLoc = S;
1505 Op->EndLoc = S;
1506 return Op;
1507 }
1508
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001509 /// Create a numeric register (e.g. $1). The exact register remains
1510 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001511 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001512 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1513 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001514 LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001515 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001516 }
1517
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001518 /// Create a register that is definitely a GPR.
1519 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001520 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001521 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1522 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1523 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001524 }
1525
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001526 /// Create a register that is definitely a FGR.
1527 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001528 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001529 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1530 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1531 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001532 }
1533
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001534 /// Create a register that is definitely a HWReg.
1535 /// This is typically only used for named registers such as $hwr_cpunum.
1536 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001537 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001538 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001539 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001540 }
1541
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001542 /// Create a register that is definitely an FCC.
1543 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001544 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001545 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1546 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1547 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001548 }
1549
1550 /// Create a register that is definitely an ACC.
1551 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001552 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001553 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1554 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1555 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001556 }
1557
1558 /// Create a register that is definitely an MSA128.
1559 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001560 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001561 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1562 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1563 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001564 }
1565
1566 /// Create a register that is definitely an MSACtrl.
1567 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001568 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001569 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1570 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1571 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001572 }
1573
David Blaikie960ea3f2014-06-08 16:18:35 +00001574 static std::unique_ptr<MipsOperand>
1575 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001576 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001577 Op->Imm.Val = Val;
1578 Op->StartLoc = S;
1579 Op->EndLoc = E;
1580 return Op;
1581 }
1582
David Blaikie960ea3f2014-06-08 16:18:35 +00001583 static std::unique_ptr<MipsOperand>
1584 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1585 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001586 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001587 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001588 Op->Mem.Off = Off;
1589 Op->StartLoc = S;
1590 Op->EndLoc = E;
1591 return Op;
1592 }
1593
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001594 static std::unique_ptr<MipsOperand>
1595 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1596 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001597 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001598
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001599 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001600 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001601 Op->StartLoc = StartLoc;
1602 Op->EndLoc = EndLoc;
1603 return Op;
1604 }
1605
Daniel Sandersd044e492016-05-09 13:10:57 +00001606 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1607 SMLoc S, SMLoc E,
1608 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001609 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001610 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001611 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1612 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001613 Op->StartLoc = S;
1614 Op->EndLoc = E;
1615 return Op;
1616 }
1617
Simon Dardis509da1a2017-02-13 16:06:48 +00001618 bool isGPRZeroAsmReg() const {
1619 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1620 }
1621
1622 bool isGPRNonZeroAsmReg() const {
1623 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1624 RegIdx.Index <= 31;
1625 }
1626
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001627 bool isGPRAsmReg() const {
1628 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001629 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001630
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001631 bool isMM16AsmReg() const {
1632 if (!(isRegIdx() && RegIdx.Kind))
1633 return false;
1634 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1635 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001636
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001637 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001638 bool isMM16AsmRegZero() const {
1639 if (!(isRegIdx() && RegIdx.Kind))
1640 return false;
1641 return (RegIdx.Index == 0 ||
1642 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1643 RegIdx.Index == 17);
1644 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001645
Zoran Jovanovic41688672015-02-10 16:36:20 +00001646 bool isMM16AsmRegMoveP() const {
1647 if (!(isRegIdx() && RegIdx.Kind))
1648 return false;
1649 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1650 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1651 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001652
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001653 bool isFGRAsmReg() const {
1654 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1655 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001656 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001657
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001658 bool isStrictlyFGRAsmReg() const {
1659 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1660 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1661 }
1662
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001663 bool isHWRegsAsmReg() const {
1664 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001665 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001666
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001667 bool isCCRAsmReg() const {
1668 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001669 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001670
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001671 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001672 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1673 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001674 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001675 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001676
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001677 bool isACCAsmReg() const {
1678 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001679 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001680
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001681 bool isCOP0AsmReg() const {
1682 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1683 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001684
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001685 bool isCOP2AsmReg() const {
1686 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001687 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001688
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001689 bool isCOP3AsmReg() const {
1690 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1691 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001692
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001693 bool isMSA128AsmReg() const {
1694 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001695 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001696
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001697 bool isMSACtrlAsmReg() const {
1698 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001699 }
1700
Jack Carterb4dbc172012-09-05 23:34:03 +00001701 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001702 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001703 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001704 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001705
Craig Topper56c590a2014-04-29 07:58:02 +00001706 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001707 switch (Kind) {
1708 case k_Immediate:
1709 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001710 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001711 OS << ">";
1712 break;
1713 case k_Memory:
1714 OS << "Mem<";
1715 Mem.Base->print(OS);
1716 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001717 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001718 OS << ">";
1719 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001720 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001721 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1722 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001723 break;
1724 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001725 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001726 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001727 case k_RegList:
1728 OS << "RegList< ";
1729 for (auto Reg : (*RegList.List))
1730 OS << Reg << " ";
1731 OS << ">";
1732 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001733 case k_RegPair:
1734 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1735 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001736 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001737 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001738
1739 bool isValidForTie(const MipsOperand &Other) const {
1740 if (Kind != Other.Kind)
1741 return false;
1742
1743 switch (Kind) {
1744 default:
1745 llvm_unreachable("Unexpected kind");
1746 return false;
1747 case k_RegisterIndex: {
1748 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1749 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1750 return Token == OtherToken;
1751 }
1752 }
1753 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001754}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001755
1756} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001757
Jack Carter9e65aa32013-03-22 00:05:30 +00001758namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001759
Jack Carter9e65aa32013-03-22 00:05:30 +00001760extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001761
1762} // end namespace llvm
1763
Jack Carter9e65aa32013-03-22 00:05:30 +00001764static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1765 return MipsInsts[Opcode];
1766}
1767
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001768static bool hasShortDelaySlot(unsigned Opcode) {
1769 switch (Opcode) {
1770 case Mips::JALS_MM:
1771 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001772 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001773 case Mips::BGEZALS_MM:
1774 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001775 return true;
1776 default:
1777 return false;
1778 }
1779}
1780
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001781static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1782 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1783 return &SRExpr->getSymbol();
1784 }
1785
1786 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1787 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1788 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1789
1790 if (LHSSym)
1791 return LHSSym;
1792
1793 if (RHSSym)
1794 return RHSSym;
1795
1796 return nullptr;
1797 }
1798
1799 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1800 return getSingleMCSymbol(UExpr->getSubExpr());
1801
1802 return nullptr;
1803}
1804
1805static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1806 if (isa<MCSymbolRefExpr>(Expr))
1807 return 1;
1808
1809 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1810 return countMCSymbolRefExpr(BExpr->getLHS()) +
1811 countMCSymbolRefExpr(BExpr->getRHS());
1812
1813 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1814 return countMCSymbolRefExpr(UExpr->getSubExpr());
1815
1816 return 0;
1817}
1818
Jack Carter9e65aa32013-03-22 00:05:30 +00001819bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001820 MCStreamer &Out,
1821 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001822 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001823 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001824 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001825
Jack Carter9e65aa32013-03-22 00:05:30 +00001826 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001827
1828 if (MCID.isBranch() || MCID.isCall()) {
1829 const unsigned Opcode = Inst.getOpcode();
1830 MCOperand Offset;
1831
1832 switch (Opcode) {
1833 default:
1834 break;
Kai Nackee0245392015-01-27 19:11:28 +00001835 case Mips::BBIT0:
1836 case Mips::BBIT032:
1837 case Mips::BBIT1:
1838 case Mips::BBIT132:
1839 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001840 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001841
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001842 case Mips::BEQ:
1843 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001844 case Mips::BEQ_MM:
1845 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001846 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001847 Offset = Inst.getOperand(2);
1848 if (!Offset.isImm())
1849 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001850 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001851 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001852 if (OffsetToAlignment(Offset.getImm(),
1853 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001854 return Error(IDLoc, "branch to misaligned address");
1855 break;
1856 case Mips::BGEZ:
1857 case Mips::BGTZ:
1858 case Mips::BLEZ:
1859 case Mips::BLTZ:
1860 case Mips::BGEZAL:
1861 case Mips::BLTZAL:
1862 case Mips::BC1F:
1863 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001864 case Mips::BGEZ_MM:
1865 case Mips::BGTZ_MM:
1866 case Mips::BLEZ_MM:
1867 case Mips::BLTZ_MM:
1868 case Mips::BGEZAL_MM:
1869 case Mips::BLTZAL_MM:
1870 case Mips::BC1F_MM:
1871 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001872 case Mips::BC1EQZC_MMR6:
1873 case Mips::BC1NEZC_MMR6:
1874 case Mips::BC2EQZC_MMR6:
1875 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001876 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001877 Offset = Inst.getOperand(1);
1878 if (!Offset.isImm())
1879 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001880 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001881 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001882 if (OffsetToAlignment(Offset.getImm(),
1883 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001884 return Error(IDLoc, "branch to misaligned address");
1885 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001886 case Mips::BGEC: case Mips::BGEC_MMR6:
1887 case Mips::BLTC: case Mips::BLTC_MMR6:
1888 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1889 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1890 case Mips::BEQC: case Mips::BEQC_MMR6:
1891 case Mips::BNEC: case Mips::BNEC_MMR6:
1892 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1893 Offset = Inst.getOperand(2);
1894 if (!Offset.isImm())
1895 break; // We'll deal with this situation later on when applying fixups.
1896 if (!isIntN(18, Offset.getImm()))
1897 return Error(IDLoc, "branch target out of range");
1898 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1899 return Error(IDLoc, "branch to misaligned address");
1900 break;
1901 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1902 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1903 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1904 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1905 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1906 Offset = Inst.getOperand(1);
1907 if (!Offset.isImm())
1908 break; // We'll deal with this situation later on when applying fixups.
1909 if (!isIntN(18, Offset.getImm()))
1910 return Error(IDLoc, "branch target out of range");
1911 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1912 return Error(IDLoc, "branch to misaligned address");
1913 break;
1914 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1915 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1916 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1917 Offset = Inst.getOperand(1);
1918 if (!Offset.isImm())
1919 break; // We'll deal with this situation later on when applying fixups.
1920 if (!isIntN(23, Offset.getImm()))
1921 return Error(IDLoc, "branch target out of range");
1922 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1923 return Error(IDLoc, "branch to misaligned address");
1924 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001925 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001926 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001927 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001928 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001929 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1930 Offset = Inst.getOperand(1);
1931 if (!Offset.isImm())
1932 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001933 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001934 return Error(IDLoc, "branch target out of range");
1935 if (OffsetToAlignment(Offset.getImm(), 2LL))
1936 return Error(IDLoc, "branch to misaligned address");
1937 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001938 }
1939 }
1940
Daniel Sandersa84989a2014-06-16 13:25:35 +00001941 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1942 // We still accept it but it is a normal nop.
1943 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1944 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1945 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1946 "nop instruction");
1947 }
1948
Kai Nackee0245392015-01-27 19:11:28 +00001949 if (hasCnMips()) {
1950 const unsigned Opcode = Inst.getOpcode();
1951 MCOperand Opnd;
1952 int Imm;
1953
1954 switch (Opcode) {
1955 default:
1956 break;
1957
1958 case Mips::BBIT0:
1959 case Mips::BBIT032:
1960 case Mips::BBIT1:
1961 case Mips::BBIT132:
1962 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1963 // The offset is handled above
1964 Opnd = Inst.getOperand(1);
1965 if (!Opnd.isImm())
1966 return Error(IDLoc, "expected immediate operand kind");
1967 Imm = Opnd.getImm();
1968 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1969 Opcode == Mips::BBIT1 ? 63 : 31))
1970 return Error(IDLoc, "immediate operand value out of range");
1971 if (Imm > 31) {
1972 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1973 : Mips::BBIT132);
1974 Inst.getOperand(1).setImm(Imm - 32);
1975 }
1976 break;
1977
Kai Nackee0245392015-01-27 19:11:28 +00001978 case Mips::SEQi:
1979 case Mips::SNEi:
1980 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1981 Opnd = Inst.getOperand(2);
1982 if (!Opnd.isImm())
1983 return Error(IDLoc, "expected immediate operand kind");
1984 Imm = Opnd.getImm();
1985 if (!isInt<10>(Imm))
1986 return Error(IDLoc, "immediate operand value out of range");
1987 break;
1988 }
1989 }
1990
Simon Dardis509da1a2017-02-13 16:06:48 +00001991 // Warn on division by zero. We're checking here as all instructions get
1992 // processed here, not just the macros that need expansion.
1993 //
1994 // The MIPS backend models most of the divison instructions and macros as
1995 // three operand instructions. The pre-R6 divide instructions however have
1996 // two operands and explicitly define HI/LO as part of the instruction,
1997 // not in the operands.
1998 unsigned FirstOp = 1;
1999 unsigned SecondOp = 2;
2000 switch (Inst.getOpcode()) {
2001 default:
2002 break;
2003 case Mips::SDivIMacro:
2004 case Mips::UDivIMacro:
2005 case Mips::DSDivIMacro:
2006 case Mips::DUDivIMacro:
2007 if (Inst.getOperand(2).getImm() == 0) {
2008 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
2009 Inst.getOperand(1).getReg() == Mips::ZERO_64)
2010 Warning(IDLoc, "dividing zero by zero");
2011 else
2012 Warning(IDLoc, "division by zero");
2013 }
2014 break;
2015 case Mips::DSDIV:
2016 case Mips::SDIV:
2017 case Mips::UDIV:
2018 case Mips::DUDIV:
2019 case Mips::UDIV_MM:
2020 case Mips::SDIV_MM:
2021 FirstOp = 0;
2022 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00002023 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00002024 case Mips::SDivMacro:
2025 case Mips::DSDivMacro:
2026 case Mips::UDivMacro:
2027 case Mips::DUDivMacro:
2028 case Mips::DIV:
2029 case Mips::DIVU:
2030 case Mips::DDIV:
2031 case Mips::DDIVU:
2032 case Mips::DIVU_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00002033 case Mips::DIV_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00002034 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
2035 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
2036 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
2037 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
2038 Warning(IDLoc, "dividing zero by zero");
2039 else
2040 Warning(IDLoc, "division by zero");
2041 }
2042 break;
2043 }
2044
Simon Atanasyan50485142016-12-12 17:40:26 +00002045 // For PIC code convert unconditional jump to unconditional branch.
2046 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
2047 inPicMode()) {
2048 MCInst BInst;
2049 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
2050 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2051 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2052 BInst.addOperand(Inst.getOperand(0));
2053 Inst = BInst;
2054 }
2055
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002056 // This expansion is not in a function called by tryExpandInstruction()
2057 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002058 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2059 inPicMode()) {
2060 warnIfNoMacro(IDLoc);
2061
2062 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2063
2064 // We can do this expansion if there's only 1 symbol in the argument
2065 // expression.
2066 if (countMCSymbolRefExpr(JalExpr) > 1)
2067 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2068
2069 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002070 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002071 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2072
2073 // FIXME: Add support for label+offset operands (currently causes an error).
2074 // FIXME: Add support for forward-declared local symbols.
2075 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002076 if (JalSym->isInSection() || JalSym->isTemporary() ||
Simon Atanasyan478220f2018-05-24 07:36:00 +00002077 (JalSym->isELF() &&
2078 cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002079 if (isABI_O32()) {
2080 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002081 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002082 // R_(MICRO)MIPS_GOT16 label
2083 // addiu $25, $25, 0
2084 // R_(MICRO)MIPS_LO16 label
2085 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002086 const MCExpr *Got16RelocExpr =
2087 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2088 const MCExpr *Lo16RelocExpr =
2089 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002090
Daniel Sandersa736b372016-04-29 13:33:12 +00002091 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2092 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2093 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2094 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002095 } else if (isABI_N32() || isABI_N64()) {
2096 // If it's a local symbol and the N32/N64 ABIs are being used,
2097 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002098 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002099 // R_(MICRO)MIPS_GOT_DISP label
2100 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002101 const MCExpr *GotDispRelocExpr =
2102 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002103
Daniel Sandersa736b372016-04-29 13:33:12 +00002104 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2105 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2106 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002107 }
2108 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002109 // If it's an external/weak symbol, we expand to:
2110 // lw/ld $25, 0($gp)
2111 // R_(MICRO)MIPS_CALL16 label
2112 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002113 const MCExpr *Call16RelocExpr =
2114 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002115
Daniel Sandersa736b372016-04-29 13:33:12 +00002116 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2117 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002118 }
2119
2120 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002121 if (IsCpRestoreSet && inMicroMipsMode())
2122 JalrInst.setOpcode(Mips::JALRS_MM);
2123 else
2124 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002125 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2126 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2127
2128 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2129 // This relocation is supposed to be an optimization hint for the linker
2130 // and is not necessary for correctness.
2131
2132 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002133 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002134 }
2135
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002136 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2137 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002138 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002139 // reference or immediate we may have to expand instructions.
2140 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002141 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002142 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2143 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002144 MCOperand &Op = Inst.getOperand(i);
2145 if (Op.isImm()) {
2146 int MemOffset = Op.getImm();
2147 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002148 // Offset can't exceed 16bit value.
Simon Atanasyana1882672018-05-24 07:36:11 +00002149 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
Nirav Dave2364748a2016-09-16 18:30:20 +00002150 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002151 }
2152 } else if (Op.isExpr()) {
2153 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002154 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002155 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002156 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002157 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002158 // Expand symbol.
Simon Atanasyana1882672018-05-24 07:36:11 +00002159 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
Nirav Dave2364748a2016-09-16 18:30:20 +00002160 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002161 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002162 } else if (!isEvaluated(Expr)) {
Simon Atanasyana1882672018-05-24 07:36:11 +00002163 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
Nirav Dave2364748a2016-09-16 18:30:20 +00002164 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002165 }
2166 }
2167 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002168 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002169 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002170
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002171 if (inMicroMipsMode()) {
Simon Dardis6a319922018-05-25 16:15:48 +00002172 if (MCID.mayLoad() && Inst.getOpcode() != Mips::LWP_MM) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002173 // Try to create 16-bit GP relative load instruction.
2174 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2175 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2176 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2177 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2178 MCOperand &Op = Inst.getOperand(i);
2179 if (Op.isImm()) {
2180 int MemOffset = Op.getImm();
2181 MCOperand &DstReg = Inst.getOperand(0);
2182 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002183 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002184 getContext().getRegisterInfo()->getRegClass(
2185 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002186 (BaseReg.getReg() == Mips::GP ||
2187 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002188
Daniel Sandersa736b372016-04-29 13:33:12 +00002189 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2190 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002191 return false;
2192 }
2193 }
2194 }
2195 } // for
2196 } // if load
2197
2198 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2199
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002200 MCOperand Opnd;
2201 int Imm;
2202
2203 switch (Inst.getOpcode()) {
2204 default:
2205 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002206 case Mips::ADDIUSP_MM:
2207 Opnd = Inst.getOperand(0);
2208 if (!Opnd.isImm())
2209 return Error(IDLoc, "expected immediate operand kind");
2210 Imm = Opnd.getImm();
2211 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2212 Imm % 4 != 0)
2213 return Error(IDLoc, "immediate operand value out of range");
2214 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002215 case Mips::SLL16_MM:
2216 case Mips::SRL16_MM:
2217 Opnd = Inst.getOperand(2);
2218 if (!Opnd.isImm())
2219 return Error(IDLoc, "expected immediate operand kind");
2220 Imm = Opnd.getImm();
2221 if (Imm < 1 || Imm > 8)
2222 return Error(IDLoc, "immediate operand value out of range");
2223 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002224 case Mips::LI16_MM:
2225 Opnd = Inst.getOperand(1);
2226 if (!Opnd.isImm())
2227 return Error(IDLoc, "expected immediate operand kind");
2228 Imm = Opnd.getImm();
2229 if (Imm < -1 || Imm > 126)
2230 return Error(IDLoc, "immediate operand value out of range");
2231 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002232 case Mips::ADDIUR2_MM:
2233 Opnd = Inst.getOperand(2);
2234 if (!Opnd.isImm())
2235 return Error(IDLoc, "expected immediate operand kind");
2236 Imm = Opnd.getImm();
2237 if (!(Imm == 1 || Imm == -1 ||
2238 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2239 return Error(IDLoc, "immediate operand value out of range");
2240 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002241 case Mips::ANDI16_MM:
2242 Opnd = Inst.getOperand(2);
2243 if (!Opnd.isImm())
2244 return Error(IDLoc, "expected immediate operand kind");
2245 Imm = Opnd.getImm();
2246 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2247 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2248 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2249 return Error(IDLoc, "immediate operand value out of range");
2250 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002251 case Mips::LBU16_MM:
2252 Opnd = Inst.getOperand(2);
2253 if (!Opnd.isImm())
2254 return Error(IDLoc, "expected immediate operand kind");
2255 Imm = Opnd.getImm();
2256 if (Imm < -1 || Imm > 14)
2257 return Error(IDLoc, "immediate operand value out of range");
2258 break;
2259 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002260 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002261 Opnd = Inst.getOperand(2);
2262 if (!Opnd.isImm())
2263 return Error(IDLoc, "expected immediate operand kind");
2264 Imm = Opnd.getImm();
2265 if (Imm < 0 || Imm > 15)
2266 return Error(IDLoc, "immediate operand value out of range");
2267 break;
2268 case Mips::LHU16_MM:
2269 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002270 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002271 Opnd = Inst.getOperand(2);
2272 if (!Opnd.isImm())
2273 return Error(IDLoc, "expected immediate operand kind");
2274 Imm = Opnd.getImm();
2275 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2276 return Error(IDLoc, "immediate operand value out of range");
2277 break;
2278 case Mips::LW16_MM:
2279 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002280 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002281 Opnd = Inst.getOperand(2);
2282 if (!Opnd.isImm())
2283 return Error(IDLoc, "expected immediate operand kind");
2284 Imm = Opnd.getImm();
2285 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2286 return Error(IDLoc, "immediate operand value out of range");
2287 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002288 case Mips::ADDIUPC_MM:
Simon Dardis6a319922018-05-25 16:15:48 +00002289 Opnd = Inst.getOperand(1);
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002290 if (!Opnd.isImm())
2291 return Error(IDLoc, "expected immediate operand kind");
Simon Dardis6a319922018-05-25 16:15:48 +00002292 Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002293 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002294 return Error(IDLoc, "immediate operand value out of range");
2295 break;
Simon Dardis6a319922018-05-25 16:15:48 +00002296 case Mips::LWP_MM:
2297 case Mips::SWP_MM:
2298 if (Inst.getOperand(0).getReg() == Mips::RA)
2299 return Error(IDLoc, "invalid operand for instruction");
2300 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002301 }
2302 }
2303
Daniel Sandersd8c07762016-04-18 12:35:36 +00002304 bool FillDelaySlot =
2305 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2306 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002307 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002308
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002309 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002310 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002311 switch (ExpandResult) {
2312 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002313 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002314 break;
2315 case MER_Success:
2316 break;
2317 case MER_Fail:
2318 return true;
2319 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002320
Daniel Sanderscda908a2016-05-16 09:10:13 +00002321 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2322 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002323 if (inMicroMipsMode()) {
Daniel Sanderscda908a2016-05-16 09:10:13 +00002324 TOut.setUsesMicroMips();
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002325 TOut.updateABIInfo(*this);
2326 }
Daniel Sanderscda908a2016-05-16 09:10:13 +00002327
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002328 // If this instruction has a delay slot and .set reorder is active,
2329 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002330 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002331 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2332 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002333 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002334
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002335 if ((Inst.getOpcode() == Mips::JalOneReg ||
2336 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2337 isPicAndNotNxxAbi()) {
2338 if (IsCpRestoreSet) {
2339 // We need a NOP between the JALR and the LW:
2340 // If .set reorder has been used, we've already emitted a NOP.
2341 // If .set noreorder has been used, we need to emit a NOP at this point.
2342 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002343 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2344 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002345
2346 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002347 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002348 } else
2349 Warning(IDLoc, "no .cprestore used in PIC mode");
2350 }
2351
Jack Carter9e65aa32013-03-22 00:05:30 +00002352 return false;
2353}
2354
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002355MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002356MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2357 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002358 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002359 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002360 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002361 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002362 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002363 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002364 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002365 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002366 case Mips::LoadAddrImm64:
2367 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2368 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2369 "expected immediate operand kind");
2370
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002371 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2372 Inst.getOperand(1),
2373 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002374 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002375 ? MER_Fail
2376 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002377 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002378 case Mips::LoadAddrReg64:
2379 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2380 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2381 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2382 "expected immediate operand kind");
2383
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002384 return expandLoadAddress(Inst.getOperand(0).getReg(),
2385 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2386 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002387 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002388 ? MER_Fail
2389 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002390 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002391 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002392 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2393 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002394 case Mips::SWM_MM:
2395 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002396 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2397 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002398 case Mips::JalOneReg:
2399 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002400 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002401 case Mips::BneImm:
2402 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002403 case Mips::BEQLImmMacro:
2404 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002405 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002406 case Mips::BLT:
2407 case Mips::BLE:
2408 case Mips::BGE:
2409 case Mips::BGT:
2410 case Mips::BLTU:
2411 case Mips::BLEU:
2412 case Mips::BGEU:
2413 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002414 case Mips::BLTL:
2415 case Mips::BLEL:
2416 case Mips::BGEL:
2417 case Mips::BGTL:
2418 case Mips::BLTUL:
2419 case Mips::BLEUL:
2420 case Mips::BGEUL:
2421 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002422 case Mips::BLTImmMacro:
2423 case Mips::BLEImmMacro:
2424 case Mips::BGEImmMacro:
2425 case Mips::BGTImmMacro:
2426 case Mips::BLTUImmMacro:
2427 case Mips::BLEUImmMacro:
2428 case Mips::BGEUImmMacro:
2429 case Mips::BGTUImmMacro:
2430 case Mips::BLTLImmMacro:
2431 case Mips::BLELImmMacro:
2432 case Mips::BGELImmMacro:
2433 case Mips::BGTLImmMacro:
2434 case Mips::BLTULImmMacro:
2435 case Mips::BLEULImmMacro:
2436 case Mips::BGEULImmMacro:
2437 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002438 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002439 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002440 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002441 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2442 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002443 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002444 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002445 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2446 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002447 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002448 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002449 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2450 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002451 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002452 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002453 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2454 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002455 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002456 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2457 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002458 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002459 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002460 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002461 case Mips::PseudoTRUNC_W_D:
2462 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2463 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002464
2465 case Mips::LoadImmSingleGPR:
2466 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2467 ? MER_Fail
2468 : MER_Success;
2469 case Mips::LoadImmSingleFGR:
2470 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2471 ? MER_Fail
2472 : MER_Success;
2473 case Mips::LoadImmDoubleGPR:
2474 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2475 ? MER_Fail
2476 : MER_Success;
2477 case Mips::LoadImmDoubleFGR:
2478 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2479 ? MER_Fail
2480 : MER_Success;
2481 case Mips::LoadImmDoubleFGR_32:
2482 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2483 ? MER_Fail
2484 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002485 case Mips::Ulh:
2486 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2487 case Mips::Ulhu:
2488 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002489 case Mips::Ush:
2490 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002491 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002492 case Mips::Usw:
2493 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002494 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002495 case Mips::NORImm64:
2496 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2497 case Mips::SLTImm64:
2498 if (isInt<16>(Inst.getOperand(2).getImm())) {
2499 Inst.setOpcode(Mips::SLTi64);
2500 return MER_NotAMacro;
2501 }
2502 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2503 case Mips::SLTUImm64:
2504 if (isInt<16>(Inst.getOperand(2).getImm())) {
2505 Inst.setOpcode(Mips::SLTiu64);
2506 return MER_NotAMacro;
2507 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002508 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002509 case Mips::ADDi: case Mips::ADDi_MM:
2510 case Mips::ADDiu: case Mips::ADDiu_MM:
2511 case Mips::SLTi: case Mips::SLTi_MM:
2512 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002513 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2514 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2515 int64_t ImmValue = Inst.getOperand(2).getImm();
2516 if (isInt<16>(ImmValue))
2517 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002518 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2519 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002520 }
2521 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002522 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2523 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2524 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002525 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2526 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2527 int64_t ImmValue = Inst.getOperand(2).getImm();
2528 if (isUInt<16>(ImmValue))
2529 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002530 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2531 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002532 }
2533 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002534 case Mips::ROL:
2535 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002536 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002537 case Mips::ROLImm:
2538 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002539 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002540 case Mips::DROL:
2541 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002542 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002543 case Mips::DROLImm:
2544 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002545 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002546 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002547 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002548 case Mips::MULImmMacro:
2549 case Mips::DMULImmMacro:
2550 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2551 case Mips::MULOMacro:
2552 case Mips::DMULOMacro:
2553 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2554 case Mips::MULOUMacro:
2555 case Mips::DMULOUMacro:
2556 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2557 case Mips::DMULMacro:
2558 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002559 case Mips::LDMacro:
2560 case Mips::SDMacro:
2561 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2562 Inst.getOpcode() == Mips::LDMacro)
2563 ? MER_Fail
2564 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002565 case Mips::SEQMacro:
2566 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2567 case Mips::SEQIMacro:
2568 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisde5ed0c2017-11-14 22:26:42 +00002569 case Mips::MFTC0: case Mips::MTTC0:
2570 case Mips::MFTGPR: case Mips::MTTGPR:
2571 case Mips::MFTLO: case Mips::MTTLO:
2572 case Mips::MFTHI: case Mips::MTTHI:
2573 case Mips::MFTACX: case Mips::MTTACX:
2574 case Mips::MFTDSP: case Mips::MTTDSP:
2575 case Mips::MFTC1: case Mips::MTTC1:
2576 case Mips::MFTHC1: case Mips::MTTHC1:
2577 case Mips::CFTC1: case Mips::CTTC1:
2578 return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002579 }
Jack Carter30a59822012-10-04 04:03:53 +00002580}
Jack Carter92995f12012-10-06 00:53:28 +00002581
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002582bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002583 MCStreamer &Out,
2584 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002585 MipsTargetStreamer &TOut = getTargetStreamer();
2586
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002587 // Create a JALR instruction which is going to replace the pseudo-JAL.
2588 MCInst JalrInst;
2589 JalrInst.setLoc(IDLoc);
2590 const MCOperand FirstRegOp = Inst.getOperand(0);
2591 const unsigned Opcode = Inst.getOpcode();
2592
2593 if (Opcode == Mips::JalOneReg) {
2594 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002595 if (IsCpRestoreSet && inMicroMipsMode()) {
2596 JalrInst.setOpcode(Mips::JALRS16_MM);
2597 JalrInst.addOperand(FirstRegOp);
2598 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002599 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002600 JalrInst.addOperand(FirstRegOp);
2601 } else {
2602 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002603 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002604 JalrInst.addOperand(FirstRegOp);
2605 }
2606 } else if (Opcode == Mips::JalTwoReg) {
2607 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002608 if (IsCpRestoreSet && inMicroMipsMode())
2609 JalrInst.setOpcode(Mips::JALRS_MM);
2610 else
2611 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002612 JalrInst.addOperand(FirstRegOp);
2613 const MCOperand SecondRegOp = Inst.getOperand(1);
2614 JalrInst.addOperand(SecondRegOp);
2615 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002616 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002617
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002618 // If .set reorder is active and branch instruction has a delay slot,
2619 // emit a NOP after it.
2620 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002621 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2622 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2623 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002624
2625 return false;
2626}
2627
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002628/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002629template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002630 unsigned BitNum = findFirstSet(x);
2631
2632 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2633}
2634
2635/// Load (or add) an immediate into a register.
2636///
2637/// @param ImmValue The immediate to load.
2638/// @param DstReg The register that will hold the immediate.
2639/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2640/// for a simple initialization.
2641/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2642/// @param IsAddress True if the immediate represents an address. False if it
2643/// is an integer.
2644/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002645bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002646 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002647 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2648 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002649 MipsTargetStreamer &TOut = getTargetStreamer();
2650
Toma Tabacu00e98672015-05-01 12:19:27 +00002651 if (!Is32BitImm && !isGP64bit()) {
2652 Error(IDLoc, "instruction requires a 64-bit architecture");
2653 return true;
2654 }
2655
Daniel Sanders03f9c012015-07-14 12:24:22 +00002656 if (Is32BitImm) {
2657 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2658 // Sign extend up to 64-bit so that the predicates match the hardware
2659 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2660 // true.
2661 ImmValue = SignExtend64<32>(ImmValue);
2662 } else {
2663 Error(IDLoc, "instruction requires a 32-bit immediate");
2664 return true;
2665 }
2666 }
2667
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002668 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2669 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2670
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002671 bool UseSrcReg = false;
2672 if (SrcReg != Mips::NoRegister)
2673 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002674
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002675 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002676 if (UseSrcReg &&
2677 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002678 // At this point we need AT to perform the expansions and we exit if it is
2679 // not available.
2680 unsigned ATReg = getATReg(IDLoc);
2681 if (!ATReg)
2682 return true;
2683 TmpReg = ATReg;
2684 }
2685
Daniel Sanders03f9c012015-07-14 12:24:22 +00002686 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002687 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002688 SrcReg = ZeroReg;
2689
2690 // This doesn't quite follow the usual ABI expectations for N32 but matches
2691 // traditional assembler behaviour. N32 would normally use addiu for both
2692 // integers and addresses.
2693 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002694 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002695 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002696 }
2697
Daniel Sandersa736b372016-04-29 13:33:12 +00002698 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002699 return false;
2700 }
2701
2702 if (isUInt<16>(ImmValue)) {
2703 unsigned TmpReg = DstReg;
2704 if (SrcReg == DstReg) {
2705 TmpReg = getATReg(IDLoc);
2706 if (!TmpReg)
2707 return true;
2708 }
2709
Daniel Sandersa736b372016-04-29 13:33:12 +00002710 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002711 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002712 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002713 return false;
2714 }
2715
2716 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002717 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002718
Toma Tabacu79588102015-04-29 10:19:56 +00002719 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2720 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002721 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002722 // Traditional behaviour seems to special case this particular value. It's
2723 // not clear why other masks are handled differently.
2724 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002725 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2726 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002727 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002728 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002729 return false;
2730 }
2731
2732 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002733 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002734 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2735 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002736 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002737 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002738 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002739 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002740 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002741 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002742
Daniel Sandersa736b372016-04-29 13:33:12 +00002743 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002744 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002745 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002746 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002747 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002748 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002749 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002750
2751 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2752 if (Is32BitImm) {
2753 Error(IDLoc, "instruction requires a 32-bit immediate");
2754 return true;
2755 }
2756
2757 // Traditionally, these immediates are shifted as little as possible and as
2758 // such we align the most significant bit to bit 15 of our temporary.
2759 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2760 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2761 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2762 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002763 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2764 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002765
2766 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002767 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002768
2769 return false;
2770 }
2771
2772 warnIfNoMacro(IDLoc);
2773
2774 // The remaining case is packed with a sequence of dsll and ori with zeros
2775 // being omitted and any neighbouring dsll's being coalesced.
2776 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2777
2778 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2779 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002780 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002781 return false;
2782
2783 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2784 // skip it and defer the shift to the next chunk.
2785 unsigned ShiftCarriedForwards = 16;
2786 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2787 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2788
2789 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002790 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2791 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002792 ShiftCarriedForwards = 0;
2793 }
2794
2795 ShiftCarriedForwards += 16;
2796 }
2797 ShiftCarriedForwards -= 16;
2798
2799 // Finish any remaining shifts left by trailing zeros.
2800 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002801 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002802
2803 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002804 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002805
Matheus Almeida3813d572014-06-19 14:39:14 +00002806 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002807}
Jack Carter92995f12012-10-06 00:53:28 +00002808
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002809bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002810 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002811 const MCOperand &ImmOp = Inst.getOperand(1);
2812 assert(ImmOp.isImm() && "expected immediate operand kind");
2813 const MCOperand &DstRegOp = Inst.getOperand(0);
2814 assert(DstRegOp.isReg() && "expected register operand kind");
2815
2816 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002817 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002818 return true;
2819
2820 return false;
2821}
2822
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002823bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2824 const MCOperand &Offset,
2825 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002826 MCStreamer &Out,
2827 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002828 // la can't produce a usable address when addresses are 64-bit.
2829 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2830 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2831 // We currently can't do this because we depend on the equality
2832 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2833 Error(IDLoc, "la used to load 64-bit address");
2834 // Continue as if we had 'dla' instead.
2835 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002836 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002837 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002838
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002839 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002840 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002841 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002842 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002843 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002844
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002845 if (!Offset.isImm())
2846 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002847 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002848
Scott Egerton24557012016-01-21 15:11:01 +00002849 if (!ABI.ArePtrs64bit()) {
2850 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2851 Is32BitAddress = true;
2852 }
2853
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002854 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002855 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002856}
2857
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002858bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2859 unsigned DstReg, unsigned SrcReg,
2860 bool Is32BitSym, SMLoc IDLoc,
2861 MCStreamer &Out,
2862 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002863 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002864 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002865 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002866 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002867
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002868 if (inPicMode() && ABI.IsO32()) {
2869 MCValue Res;
2870 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2871 Error(IDLoc, "expected relocatable expression");
2872 return true;
2873 }
2874 if (Res.getSymB() != nullptr) {
2875 Error(IDLoc, "expected relocatable expression with only one symbol");
2876 return true;
2877 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002878
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002879 // The case where the result register is $25 is somewhat special. If the
2880 // symbol in the final relocation is external and not modified with a
2881 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2882 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002883 Res.getConstant() == 0 &&
2884 !(Res.getSymA()->getSymbol().isInSection() ||
2885 Res.getSymA()->getSymbol().isTemporary() ||
2886 (Res.getSymA()->getSymbol().isELF() &&
2887 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2888 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002889 const MCExpr *CallExpr =
2890 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2891 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2892 MCOperand::createExpr(CallExpr), IDLoc, STI);
2893 return false;
2894 }
2895
2896 // The remaining cases are:
2897 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2898 // >addiu $tmp, $tmp, %lo(offset)
2899 // >addiu $rd, $tmp, $rs
2900 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2901 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2902 // >addiu $rd, $tmp, $rs
2903 // The addiu's marked with a '>' may be omitted if they are redundant. If
2904 // this happens then the last instruction must use $rd as the result
2905 // register.
2906 const MipsMCExpr *GotExpr =
2907 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2908 const MCExpr *LoExpr = nullptr;
2909 if (Res.getSymA()->getSymbol().isInSection() ||
2910 Res.getSymA()->getSymbol().isTemporary())
2911 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2912 else if (Res.getConstant() != 0) {
2913 // External symbols fully resolve the symbol with just the %got(symbol)
2914 // but we must still account for any offset to the symbol for expressions
2915 // like symbol+8.
2916 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2917 }
2918
2919 unsigned TmpReg = DstReg;
2920 if (UseSrcReg &&
2921 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2922 SrcReg)) {
2923 // If $rs is the same as $rd, we need to use AT.
2924 // If it is not available we exit.
2925 unsigned ATReg = getATReg(IDLoc);
2926 if (!ATReg)
2927 return true;
2928 TmpReg = ATReg;
2929 }
2930
2931 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2932 MCOperand::createExpr(GotExpr), IDLoc, STI);
2933
2934 if (LoExpr)
2935 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2936 IDLoc, STI);
2937
2938 if (UseSrcReg)
2939 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2940
2941 return false;
2942 }
2943
Simon Dardisda96c432017-06-30 15:44:27 +00002944 if (inPicMode() && ABI.ArePtrs64bit()) {
2945 MCValue Res;
2946 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2947 Error(IDLoc, "expected relocatable expression");
2948 return true;
2949 }
2950 if (Res.getSymB() != nullptr) {
2951 Error(IDLoc, "expected relocatable expression with only one symbol");
2952 return true;
2953 }
2954
2955 // The case where the result register is $25 is somewhat special. If the
2956 // symbol in the final relocation is external and not modified with a
2957 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2958 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2959 Res.getConstant() == 0 &&
2960 !(Res.getSymA()->getSymbol().isInSection() ||
2961 Res.getSymA()->getSymbol().isTemporary() ||
2962 (Res.getSymA()->getSymbol().isELF() &&
2963 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2964 ELF::STB_LOCAL))) {
2965 const MCExpr *CallExpr =
2966 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2967 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2968 MCOperand::createExpr(CallExpr), IDLoc, STI);
2969 return false;
2970 }
2971
2972 // The remaining cases are:
2973 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2974 // >daddiu $tmp, $tmp, offset
2975 // >daddu $rd, $tmp, $rs
2976 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2977 // this happens then the last instruction must use $rd as the result
2978 // register.
2979 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2980 Res.getSymA(),
2981 getContext());
2982 const MCExpr *LoExpr = nullptr;
2983 if (Res.getConstant() != 0) {
2984 // Symbols fully resolve with just the %got_disp(symbol) but we
2985 // must still account for any offset to the symbol for
2986 // expressions like symbol+8.
2987 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2988
2989 // FIXME: Offsets greater than 16 bits are not yet implemented.
2990 // FIXME: The correct range is a 32-bit sign-extended number.
2991 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2992 Error(IDLoc, "macro instruction uses large offset, which is not "
2993 "currently supported");
2994 return true;
2995 }
2996 }
2997
2998 unsigned TmpReg = DstReg;
2999 if (UseSrcReg &&
3000 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
3001 SrcReg)) {
3002 // If $rs is the same as $rd, we need to use AT.
3003 // If it is not available we exit.
3004 unsigned ATReg = getATReg(IDLoc);
3005 if (!ATReg)
3006 return true;
3007 TmpReg = ATReg;
3008 }
3009
3010 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
3011 MCOperand::createExpr(GotExpr), IDLoc, STI);
3012
3013 if (LoExpr)
3014 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3015 IDLoc, STI);
3016
3017 if (UseSrcReg)
3018 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
3019
3020 return false;
3021 }
3022
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003023 const MipsMCExpr *HiExpr =
3024 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
3025 const MipsMCExpr *LoExpr =
3026 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00003027
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003028 // This is the 64-bit symbol address expansion.
3029 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00003030 // We need AT for the 64-bit expansion in the cases where the optional
3031 // source register is the destination register and for the superscalar
3032 // scheduled form.
3033 //
3034 // If it is not available we exit if the destination is the same as the
3035 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003036
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003037 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003038 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003039 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003040 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003041
Simon Dardis3aa8a902017-02-06 12:43:46 +00003042 bool RdRegIsRsReg =
3043 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
3044
3045 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
3046 unsigned ATReg = getATReg(IDLoc);
3047
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003048 // If $rs is the same as $rd:
3049 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
3050 // daddiu $at, $at, %higher(sym)
3051 // dsll $at, $at, 16
3052 // daddiu $at, $at, %hi(sym)
3053 // dsll $at, $at, 16
3054 // daddiu $at, $at, %lo(sym)
3055 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00003056 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3057 STI);
3058 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3059 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3060 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3061 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3062 IDLoc, STI);
3063 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3064 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3065 IDLoc, STI);
3066 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003067
3068 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00003069 } else if (canUseATReg() && !RdRegIsRsReg) {
3070 unsigned ATReg = getATReg(IDLoc);
3071
3072 // If the $rs is different from $rd or if $rs isn't specified and we
3073 // have $at available:
3074 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3075 // lui $at, %hi(sym)
3076 // daddiu $rd, $rd, %higher(sym)
3077 // daddiu $at, $at, %lo(sym)
3078 // dsll32 $rd, $rd, 0
3079 // daddu $rd, $rd, $at
3080 // (daddu $rd, $rd, $rs)
3081 //
3082 // Which is preferred for superscalar issue.
3083 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3084 STI);
3085 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3086 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3087 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3088 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3089 IDLoc, STI);
3090 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3091 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3092 if (UseSrcReg)
3093 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3094
3095 return false;
3096 } else if (!canUseATReg() && !RdRegIsRsReg) {
3097 // Otherwise, synthesize the address in the destination register
3098 // serially:
3099 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3100 // daddiu $rd, $rd, %higher(sym)
3101 // dsll $rd, $rd, 16
3102 // daddiu $rd, $rd, %hi(sym)
3103 // dsll $rd, $rd, 16
3104 // daddiu $rd, $rd, %lo(sym)
3105 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3106 STI);
3107 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3108 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3109 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3110 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3111 MCOperand::createExpr(HiExpr), IDLoc, STI);
3112 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3113 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3114 MCOperand::createExpr(LoExpr), IDLoc, STI);
3115 if (UseSrcReg)
3116 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3117
3118 return false;
3119 } else {
3120 // We have a case where SrcReg == DstReg and we don't have $at
3121 // available. We can't expand this case, so error out appropriately.
3122 assert(SrcReg == DstReg && !canUseATReg() &&
3123 "Could have expanded dla but didn't?");
3124 reportParseError(IDLoc,
3125 "pseudo-instruction requires $at, which is not available");
3126 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003127 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003128 }
3129
3130 // And now, the 32-bit symbol address expansion:
3131 // If $rs is the same as $rd:
3132 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3133 // ori $at, $at, %lo(sym)
3134 // addu $rd, $at, $rd
3135 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3136 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3137 // ori $rd, $rd, %lo(sym)
3138 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003139 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003140 if (UseSrcReg &&
3141 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003142 // If $rs is the same as $rd, we need to use AT.
3143 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003144 unsigned ATReg = getATReg(IDLoc);
3145 if (!ATReg)
3146 return true;
3147 TmpReg = ATReg;
3148 }
3149
Daniel Sandersa736b372016-04-29 13:33:12 +00003150 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3151 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3152 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003153
Toma Tabacufb9d1252015-06-22 12:08:39 +00003154 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003155 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003156 else
Scott Egerton24557012016-01-21 15:11:01 +00003157 assert(
3158 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003159
Toma Tabacu674825c2015-06-16 12:16:24 +00003160 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003161}
3162
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003163// Each double-precision register DO-D15 overlaps with two of the single
3164// precision registers F0-F31. As an example, all of the following hold true:
3165// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3166static unsigned nextReg(unsigned Reg) {
3167 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3168 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3169 switch (Reg) {
3170 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3171 case Mips::ZERO: return Mips::AT;
3172 case Mips::AT: return Mips::V0;
3173 case Mips::V0: return Mips::V1;
3174 case Mips::V1: return Mips::A0;
3175 case Mips::A0: return Mips::A1;
3176 case Mips::A1: return Mips::A2;
3177 case Mips::A2: return Mips::A3;
3178 case Mips::A3: return Mips::T0;
3179 case Mips::T0: return Mips::T1;
3180 case Mips::T1: return Mips::T2;
3181 case Mips::T2: return Mips::T3;
3182 case Mips::T3: return Mips::T4;
3183 case Mips::T4: return Mips::T5;
3184 case Mips::T5: return Mips::T6;
3185 case Mips::T6: return Mips::T7;
3186 case Mips::T7: return Mips::S0;
3187 case Mips::S0: return Mips::S1;
3188 case Mips::S1: return Mips::S2;
3189 case Mips::S2: return Mips::S3;
3190 case Mips::S3: return Mips::S4;
3191 case Mips::S4: return Mips::S5;
3192 case Mips::S5: return Mips::S6;
3193 case Mips::S6: return Mips::S7;
3194 case Mips::S7: return Mips::T8;
3195 case Mips::T8: return Mips::T9;
3196 case Mips::T9: return Mips::K0;
3197 case Mips::K0: return Mips::K1;
3198 case Mips::K1: return Mips::GP;
3199 case Mips::GP: return Mips::SP;
3200 case Mips::SP: return Mips::FP;
3201 case Mips::FP: return Mips::RA;
3202 case Mips::RA: return Mips::ZERO;
3203 case Mips::D0: return Mips::F1;
3204 case Mips::D1: return Mips::F3;
3205 case Mips::D2: return Mips::F5;
3206 case Mips::D3: return Mips::F7;
3207 case Mips::D4: return Mips::F9;
3208 case Mips::D5: return Mips::F11;
3209 case Mips::D6: return Mips::F13;
3210 case Mips::D7: return Mips::F15;
3211 case Mips::D8: return Mips::F17;
3212 case Mips::D9: return Mips::F19;
3213 case Mips::D10: return Mips::F21;
3214 case Mips::D11: return Mips::F23;
3215 case Mips::D12: return Mips::F25;
3216 case Mips::D13: return Mips::F27;
3217 case Mips::D14: return Mips::F29;
3218 case Mips::D15: return Mips::F31;
3219 }
3220}
3221
3222// FIXME: This method is too general. In principle we should compute the number
3223// of instructions required to synthesize the immediate inline compared to
3224// synthesizing the address inline and relying on non .text sections.
3225// For static O32 and N32 this may yield a small benefit, for static N64 this is
3226// likely to yield a much larger benefit as we have to synthesize a 64bit
3227// address to load a 64 bit value.
3228bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3229 MCSymbol *Sym) {
3230 unsigned ATReg = getATReg(IDLoc);
3231 if (!ATReg)
3232 return true;
3233
3234 if(IsPicEnabled) {
3235 const MCExpr *GotSym =
3236 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3237 const MipsMCExpr *GotExpr =
3238 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3239
3240 if(isABI_O32() || isABI_N32()) {
3241 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3242 IDLoc, STI);
3243 } else { //isABI_N64()
3244 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3245 IDLoc, STI);
3246 }
3247 } else { //!IsPicEnabled
3248 const MCExpr *HiSym =
3249 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3250 const MipsMCExpr *HiExpr =
3251 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3252
3253 // FIXME: This is technically correct but gives a different result to gas,
3254 // but gas is incomplete there (it has a fixme noting it doesn't work with
3255 // 64-bit addresses).
3256 // FIXME: With -msym32 option, the address expansion for N64 should probably
3257 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3258 // symbol's value is considered sign extended.
3259 if(isABI_O32() || isABI_N32()) {
3260 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3261 } else { //isABI_N64()
3262 const MCExpr *HighestSym =
3263 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3264 const MipsMCExpr *HighestExpr =
3265 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3266 const MCExpr *HigherSym =
3267 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3268 const MipsMCExpr *HigherExpr =
3269 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3270
3271 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3272 STI);
3273 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3274 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3275 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3276 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3277 IDLoc, STI);
3278 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3279 }
3280 }
3281 return false;
3282}
3283
3284bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3285 bool Is64FPU, SMLoc IDLoc,
3286 MCStreamer &Out,
3287 const MCSubtargetInfo *STI) {
3288 MipsTargetStreamer &TOut = getTargetStreamer();
3289 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3290 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3291 "Invalid instruction operand.");
3292
3293 unsigned FirstReg = Inst.getOperand(0).getReg();
3294 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3295
3296 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3297 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3298 // exponent field), convert it to double (e.g. 1 to 1.0)
3299 if ((HiImmOp64 & 0x7ff00000) == 0) {
3300 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3301 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3302 }
3303
3304 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3305 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3306
3307 if (IsSingle) {
3308 // Conversion of a double in an uint64_t to a float in a uint32_t,
3309 // retaining the bit pattern of a float.
3310 uint32_t ImmOp32;
3311 double doubleImm = BitsToDouble(ImmOp64);
3312 float tmp_float = static_cast<float>(doubleImm);
3313 ImmOp32 = FloatToBits(tmp_float);
3314
3315 if (IsGPR) {
3316 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3317 Out, STI))
3318 return true;
3319 return false;
3320 } else {
3321 unsigned ATReg = getATReg(IDLoc);
3322 if (!ATReg)
3323 return true;
3324 if (LoImmOp64 == 0) {
3325 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3326 Out, STI))
3327 return true;
3328 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3329 return false;
3330 }
3331
3332 MCSection *CS = getStreamer().getCurrentSectionOnly();
3333 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3334 // where appropriate.
3335 MCSection *ReadOnlySection = getContext().getELFSection(
3336 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3337
3338 MCSymbol *Sym = getContext().createTempSymbol();
3339 const MCExpr *LoSym =
3340 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3341 const MipsMCExpr *LoExpr =
3342 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3343
3344 getStreamer().SwitchSection(ReadOnlySection);
3345 getStreamer().EmitLabel(Sym, IDLoc);
3346 getStreamer().EmitIntValue(ImmOp32, 4);
3347 getStreamer().SwitchSection(CS);
3348
3349 if(emitPartialAddress(TOut, IDLoc, Sym))
3350 return true;
3351 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3352 MCOperand::createExpr(LoExpr), IDLoc, STI);
3353 }
3354 return false;
3355 }
3356
3357 // if(!IsSingle)
3358 unsigned ATReg = getATReg(IDLoc);
3359 if (!ATReg)
3360 return true;
3361
3362 if (IsGPR) {
3363 if (LoImmOp64 == 0) {
3364 if(isABI_N32() || isABI_N64()) {
3365 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3366 IDLoc, Out, STI))
3367 return true;
3368 return false;
3369 } else {
3370 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3371 IDLoc, Out, STI))
3372 return true;
3373
3374 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3375 IDLoc, Out, STI))
3376 return true;
3377 return false;
3378 }
3379 }
3380
3381 MCSection *CS = getStreamer().getCurrentSectionOnly();
3382 MCSection *ReadOnlySection = getContext().getELFSection(
3383 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3384
3385 MCSymbol *Sym = getContext().createTempSymbol();
3386 const MCExpr *LoSym =
3387 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3388 const MipsMCExpr *LoExpr =
3389 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3390
3391 getStreamer().SwitchSection(ReadOnlySection);
3392 getStreamer().EmitLabel(Sym, IDLoc);
3393 getStreamer().EmitIntValue(HiImmOp64, 4);
3394 getStreamer().EmitIntValue(LoImmOp64, 4);
3395 getStreamer().SwitchSection(CS);
3396
3397 if(emitPartialAddress(TOut, IDLoc, Sym))
3398 return true;
3399 if(isABI_N64())
3400 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3401 MCOperand::createExpr(LoExpr), IDLoc, STI);
3402 else
3403 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3404 MCOperand::createExpr(LoExpr), IDLoc, STI);
3405
3406 if(isABI_N32() || isABI_N64())
3407 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3408 else {
3409 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3410 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3411 }
3412 return false;
3413 } else { // if(!IsGPR && !IsSingle)
3414 if ((LoImmOp64 == 0) &&
3415 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3416 // FIXME: In the case where the constant is zero, we can load the
3417 // register directly from the zero register.
3418 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3419 Out, STI))
3420 return true;
3421 if (isABI_N32() || isABI_N64())
3422 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3423 else if (hasMips32r2()) {
3424 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3425 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3426 } else {
3427 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3428 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3429 }
3430 return false;
3431 }
3432
3433 MCSection *CS = getStreamer().getCurrentSectionOnly();
3434 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3435 // where appropriate.
3436 MCSection *ReadOnlySection = getContext().getELFSection(
3437 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3438
3439 MCSymbol *Sym = getContext().createTempSymbol();
3440 const MCExpr *LoSym =
3441 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3442 const MipsMCExpr *LoExpr =
3443 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3444
3445 getStreamer().SwitchSection(ReadOnlySection);
3446 getStreamer().EmitLabel(Sym, IDLoc);
3447 getStreamer().EmitIntValue(HiImmOp64, 4);
3448 getStreamer().EmitIntValue(LoImmOp64, 4);
3449 getStreamer().SwitchSection(CS);
3450
3451 if(emitPartialAddress(TOut, IDLoc, Sym))
3452 return true;
3453 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3454 MCOperand::createExpr(LoExpr), IDLoc, STI);
3455 }
3456 return false;
3457}
3458
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003459bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3460 MCStreamer &Out,
3461 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003462 MipsTargetStreamer &TOut = getTargetStreamer();
3463
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003464 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3465 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003466
3467 MCOperand Offset = Inst.getOperand(0);
3468 if (Offset.isExpr()) {
3469 Inst.clear();
3470 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003471 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3472 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3473 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003474 } else {
3475 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003476 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003477 // If offset fits into 11 bits then this instruction becomes microMIPS
3478 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003479 if (inMicroMipsMode())
3480 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003481 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003482 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003483 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003484 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003485 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003486 Inst.clear();
3487 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003488 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3489 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3490 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003491 }
3492 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003493 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003494
Zoran Jovanovicada70912015-09-07 11:56:37 +00003495 // If .set reorder is active and branch instruction has a delay slot,
3496 // emit a NOP after it.
3497 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3498 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003499 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003500
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003501 return false;
3502}
3503
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003504bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3505 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003506 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003507 const MCOperand &DstRegOp = Inst.getOperand(0);
3508 assert(DstRegOp.isReg() && "expected register operand kind");
3509
3510 const MCOperand &ImmOp = Inst.getOperand(1);
3511 assert(ImmOp.isImm() && "expected immediate operand kind");
3512
3513 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003514 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3515 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003516
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003517 bool IsLikely = false;
3518
Toma Tabacue1e460d2015-06-11 10:36:10 +00003519 unsigned OpCode = 0;
3520 switch(Inst.getOpcode()) {
3521 case Mips::BneImm:
3522 OpCode = Mips::BNE;
3523 break;
3524 case Mips::BeqImm:
3525 OpCode = Mips::BEQ;
3526 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003527 case Mips::BEQLImmMacro:
3528 OpCode = Mips::BEQL;
3529 IsLikely = true;
3530 break;
3531 case Mips::BNELImmMacro:
3532 OpCode = Mips::BNEL;
3533 IsLikely = true;
3534 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003535 default:
3536 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3537 break;
3538 }
3539
3540 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003541 if (ImmValue == 0) {
3542 if (IsLikely) {
3543 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3544 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3545 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3546 } else
3547 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3548 STI);
3549 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003550 warnIfNoMacro(IDLoc);
3551
3552 unsigned ATReg = getATReg(IDLoc);
3553 if (!ATReg)
3554 return true;
3555
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003556 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003557 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003558 return true;
3559
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003560 if (IsLikely) {
3561 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3562 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3563 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3564 } else
3565 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003566 }
3567 return false;
3568}
3569
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003570void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Simon Atanasyana1882672018-05-24 07:36:11 +00003571 const MCSubtargetInfo *STI, bool IsLoad) {
Simon Atanasyan478220f2018-05-24 07:36:00 +00003572 if (IsLoad)
Simon Atanasyana1882672018-05-24 07:36:11 +00003573 expandLoadInst(Inst, IDLoc, Out, STI);
Simon Atanasyan478220f2018-05-24 07:36:00 +00003574 else
Simon Atanasyana1882672018-05-24 07:36:11 +00003575 expandStoreInst(Inst, IDLoc, Out, STI);
Daniel Sandersfba875f2016-04-29 13:43:45 +00003576}
3577
3578void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Simon Atanasyana1882672018-05-24 07:36:11 +00003579 const MCSubtargetInfo *STI) {
Simon Atanasyanbe8a42e2018-05-24 07:36:06 +00003580 const MCOperand &DstRegOp = Inst.getOperand(0);
3581 assert(DstRegOp.isReg() && "expected register operand kind");
3582 const MCOperand &BaseRegOp = Inst.getOperand(1);
3583 assert(BaseRegOp.isReg() && "expected register operand kind");
3584 const MCOperand &OffsetOp = Inst.getOperand(2);
Daniel Sandersfba875f2016-04-29 13:43:45 +00003585
Simon Atanasyanbe8a42e2018-05-24 07:36:06 +00003586 MipsTargetStreamer &TOut = getTargetStreamer();
3587 unsigned DstReg = DstRegOp.getReg();
3588 unsigned BaseReg = BaseRegOp.getReg();
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003589 unsigned TmpReg = DstReg;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003590
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003591 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003592 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3593 unsigned DstRegClassID =
3594 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3595 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3596 (DstRegClassID == Mips::GPR64RegClassID);
3597
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003598 if (!IsGPR || (BaseReg == DstReg)) {
3599 // At this point we need AT to perform the expansions
3600 // and we exit if it is not available.
3601 TmpReg = getATReg(IDLoc);
3602 if (!TmpReg)
3603 return;
3604 }
3605
Simon Atanasyana1882672018-05-24 07:36:11 +00003606 if (OffsetOp.isImm()) {
Daniel Sandersfba875f2016-04-29 13:43:45 +00003607 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003608 OffsetOp.getImm(), TmpReg, IDLoc, STI);
3609 } else {
3610 assert(OffsetOp.isExpr() && "expected expression operand kind");
3611 const MCExpr *ExprOffset = OffsetOp.getExpr();
3612 MCOperand LoOperand = MCOperand::createExpr(
3613 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3614 MCOperand HiOperand = MCOperand::createExpr(
3615 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003616 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003617 LoOperand, TmpReg, IDLoc, STI);
Daniel Sandersfba875f2016-04-29 13:43:45 +00003618 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003619}
3620
3621void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Simon Atanasyana1882672018-05-24 07:36:11 +00003622 const MCSubtargetInfo *STI) {
Simon Atanasyanbe8a42e2018-05-24 07:36:06 +00003623 const MCOperand &SrcRegOp = Inst.getOperand(0);
3624 assert(SrcRegOp.isReg() && "expected register operand kind");
3625 const MCOperand &BaseRegOp = Inst.getOperand(1);
3626 assert(BaseRegOp.isReg() && "expected register operand kind");
3627 const MCOperand &OffsetOp = Inst.getOperand(2);
Daniel Sandersfba875f2016-04-29 13:43:45 +00003628
Simon Atanasyanbe8a42e2018-05-24 07:36:06 +00003629 MipsTargetStreamer &TOut = getTargetStreamer();
3630 unsigned SrcReg = SrcRegOp.getReg();
3631 unsigned BaseReg = BaseRegOp.getReg();
Daniel Sandersfba875f2016-04-29 13:43:45 +00003632
Simon Atanasyana1882672018-05-24 07:36:11 +00003633 if (OffsetOp.isImm()) {
Daniel Sanders241c6792016-05-12 14:01:50 +00003634 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
Simon Atanasyanbe8a42e2018-05-24 07:36:06 +00003635 OffsetOp.getImm(),
Daniel Sanders241c6792016-05-12 14:01:50 +00003636 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3637 return;
3638 }
3639
Daniel Sandersfba875f2016-04-29 13:43:45 +00003640 unsigned ATReg = getATReg(IDLoc);
3641 if (!ATReg)
3642 return;
3643
Simon Atanasyanbe8a42e2018-05-24 07:36:06 +00003644 assert(OffsetOp.isExpr() && "expected expression operand kind");
3645 const MCExpr *ExprOffset = OffsetOp.getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003646 MCOperand LoOperand = MCOperand::createExpr(
3647 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3648 MCOperand HiOperand = MCOperand::createExpr(
3649 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003650 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3651 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003652}
3653
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003654bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3655 MCStreamer &Out,
3656 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003657 unsigned OpNum = Inst.getNumOperands();
3658 unsigned Opcode = Inst.getOpcode();
3659 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3660
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003661 assert(Inst.getOperand(OpNum - 1).isImm() &&
3662 Inst.getOperand(OpNum - 2).isReg() &&
3663 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003664
3665 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3666 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003667 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3668 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3669 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3670 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003671 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003672 if (inMicroMipsMode() && hasMips32r6())
3673 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3674 else
3675 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3676 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003677
3678 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003679 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003680 return false;
3681}
3682
Toma Tabacu1a108322015-06-17 13:20:24 +00003683bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003684 MCStreamer &Out,
3685 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003686 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003687 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003688 unsigned PseudoOpcode = Inst.getOpcode();
3689 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003690 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003691 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3692
3693 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003694 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003695
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003696 unsigned TrgReg;
3697 if (TrgOp.isReg())
3698 TrgReg = TrgOp.getReg();
3699 else if (TrgOp.isImm()) {
3700 warnIfNoMacro(IDLoc);
3701 EmittedNoMacroWarning = true;
3702
3703 TrgReg = getATReg(IDLoc);
3704 if (!TrgReg)
3705 return true;
3706
3707 switch(PseudoOpcode) {
3708 default:
3709 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3710 case Mips::BLTImmMacro:
3711 PseudoOpcode = Mips::BLT;
3712 break;
3713 case Mips::BLEImmMacro:
3714 PseudoOpcode = Mips::BLE;
3715 break;
3716 case Mips::BGEImmMacro:
3717 PseudoOpcode = Mips::BGE;
3718 break;
3719 case Mips::BGTImmMacro:
3720 PseudoOpcode = Mips::BGT;
3721 break;
3722 case Mips::BLTUImmMacro:
3723 PseudoOpcode = Mips::BLTU;
3724 break;
3725 case Mips::BLEUImmMacro:
3726 PseudoOpcode = Mips::BLEU;
3727 break;
3728 case Mips::BGEUImmMacro:
3729 PseudoOpcode = Mips::BGEU;
3730 break;
3731 case Mips::BGTUImmMacro:
3732 PseudoOpcode = Mips::BGTU;
3733 break;
3734 case Mips::BLTLImmMacro:
3735 PseudoOpcode = Mips::BLTL;
3736 break;
3737 case Mips::BLELImmMacro:
3738 PseudoOpcode = Mips::BLEL;
3739 break;
3740 case Mips::BGELImmMacro:
3741 PseudoOpcode = Mips::BGEL;
3742 break;
3743 case Mips::BGTLImmMacro:
3744 PseudoOpcode = Mips::BGTL;
3745 break;
3746 case Mips::BLTULImmMacro:
3747 PseudoOpcode = Mips::BLTUL;
3748 break;
3749 case Mips::BLEULImmMacro:
3750 PseudoOpcode = Mips::BLEUL;
3751 break;
3752 case Mips::BGEULImmMacro:
3753 PseudoOpcode = Mips::BGEUL;
3754 break;
3755 case Mips::BGTULImmMacro:
3756 PseudoOpcode = Mips::BGTUL;
3757 break;
3758 }
3759
3760 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003761 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003762 return true;
3763 }
3764
Toma Tabacu1a108322015-06-17 13:20:24 +00003765 switch (PseudoOpcode) {
3766 case Mips::BLT:
3767 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003768 case Mips::BLTL:
3769 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003770 AcceptsEquality = false;
3771 ReverseOrderSLT = false;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003772 IsUnsigned =
3773 ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003774 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003775 ZeroSrcOpcode = Mips::BGTZ;
3776 ZeroTrgOpcode = Mips::BLTZ;
3777 break;
3778 case Mips::BLE:
3779 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003780 case Mips::BLEL:
3781 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003782 AcceptsEquality = true;
3783 ReverseOrderSLT = true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003784 IsUnsigned =
3785 ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003786 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003787 ZeroSrcOpcode = Mips::BGEZ;
3788 ZeroTrgOpcode = Mips::BLEZ;
3789 break;
3790 case Mips::BGE:
3791 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003792 case Mips::BGEL:
3793 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003794 AcceptsEquality = true;
3795 ReverseOrderSLT = false;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003796 IsUnsigned =
3797 ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003798 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003799 ZeroSrcOpcode = Mips::BLEZ;
3800 ZeroTrgOpcode = Mips::BGEZ;
3801 break;
3802 case Mips::BGT:
3803 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003804 case Mips::BGTL:
3805 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003806 AcceptsEquality = false;
3807 ReverseOrderSLT = true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003808 IsUnsigned =
3809 ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003810 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003811 ZeroSrcOpcode = Mips::BLTZ;
3812 ZeroTrgOpcode = Mips::BGTZ;
3813 break;
3814 default:
3815 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3816 }
3817
Toma Tabacu1a108322015-06-17 13:20:24 +00003818 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3819 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3820 if (IsSrcRegZero && IsTrgRegZero) {
3821 // FIXME: All of these Opcode-specific if's are needed for compatibility
3822 // with GAS' behaviour. However, they may not generate the most efficient
3823 // code in some circumstances.
3824 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003825 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3826 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003827 return false;
3828 }
3829 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003830 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3831 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003832 Warning(IDLoc, "branch is always taken");
3833 return false;
3834 }
3835 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003836 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3837 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003838 Warning(IDLoc, "branch is always taken");
3839 return false;
3840 }
3841 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003842 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3843 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003844 return false;
3845 }
3846 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003847 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3848 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003849 return false;
3850 }
3851 if (AcceptsEquality) {
3852 // If both registers are $0 and the pseudo-branch accepts equality, it
3853 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003854 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3855 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003856 Warning(IDLoc, "branch is always taken");
3857 return false;
3858 }
3859 // If both registers are $0 and the pseudo-branch does not accept
3860 // equality, it will never be taken, so we don't have to emit anything.
3861 return false;
3862 }
3863 if (IsSrcRegZero || IsTrgRegZero) {
3864 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3865 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3866 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3867 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3868 // the pseudo-branch will never be taken, so we don't emit anything.
3869 // This only applies to unsigned pseudo-branches.
3870 return false;
3871 }
3872 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3873 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3874 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3875 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3876 // the pseudo-branch will always be taken, so we emit an unconditional
3877 // branch.
3878 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003879 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3880 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003881 Warning(IDLoc, "branch is always taken");
3882 return false;
3883 }
3884 if (IsUnsigned) {
3885 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3886 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3887 // the pseudo-branch will be taken only when the non-zero register is
3888 // different from 0, so we emit a BNEZ.
3889 //
3890 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3891 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3892 // the pseudo-branch will be taken only when the non-zero register is
3893 // equal to 0, so we emit a BEQZ.
3894 //
3895 // Because only BLEU and BGEU branch on equality, we can use the
3896 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003897 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3898 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3899 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003900 return false;
3901 }
3902 // If we have a signed pseudo-branch and one of the registers is $0,
3903 // we can use an appropriate compare-to-zero branch. We select which one
3904 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003905 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3906 IsSrcRegZero ? TrgReg : SrcReg,
3907 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003908 return false;
3909 }
3910
3911 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3912 // expansions. If it is not available, we return.
3913 unsigned ATRegNum = getATReg(IDLoc);
3914 if (!ATRegNum)
3915 return true;
3916
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003917 if (!EmittedNoMacroWarning)
3918 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003919
3920 // SLT fits well with 2 of our 4 pseudo-branches:
3921 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3922 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3923 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3924 // This is accomplished by using a BNEZ with the result of the SLT.
3925 //
3926 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
Hiroshi Inoue7f9f92f2018-02-22 07:48:29 +00003927 // and BLE with BGT), so we change the BNEZ into a BEQZ.
Toma Tabacu1a108322015-06-17 13:20:24 +00003928 // Because only BGE and BLE branch on equality, we can use the
3929 // AcceptsEquality variable to decide when to emit the BEQZ.
3930 // Note that the order of the SLT arguments doesn't change between
3931 // opposites.
3932 //
3933 // The same applies to the unsigned variants, except that SLTu is used
3934 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003935 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3936 ReverseOrderSLT ? TrgReg : SrcReg,
3937 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003938
Daniel Sandersa736b372016-04-29 13:33:12 +00003939 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3940 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3941 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3942 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003943 return false;
3944}
3945
Simon Dardis509da1a2017-02-13 16:06:48 +00003946// Expand a integer division macro.
3947//
3948// Notably we don't have to emit a warning when encountering $rt as the $zero
3949// register, or 0 as an immediate. processInstruction() has already done that.
3950//
3951// The destination register can only be $zero when expanding (S)DivIMacro or
3952// D(S)DivMacro.
3953
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003954bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3955 const MCSubtargetInfo *STI, const bool IsMips64,
3956 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003957 MipsTargetStreamer &TOut = getTargetStreamer();
3958
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003959 warnIfNoMacro(IDLoc);
3960
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003961 const MCOperand &RdRegOp = Inst.getOperand(0);
3962 assert(RdRegOp.isReg() && "expected register operand kind");
3963 unsigned RdReg = RdRegOp.getReg();
3964
3965 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003966 assert(RsRegOp.isReg() && "expected register operand kind");
3967 unsigned RsReg = RsRegOp.getReg();
3968
Simon Dardis12850ee2017-01-31 10:49:24 +00003969 unsigned RtReg;
3970 int64_t ImmValue;
3971
3972 const MCOperand &RtOp = Inst.getOperand(2);
3973 assert((RtOp.isReg() || RtOp.isImm()) &&
3974 "expected register or immediate operand kind");
3975 if (RtOp.isReg())
3976 RtReg = RtOp.getReg();
3977 else
3978 ImmValue = RtOp.getImm();
3979
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003980 unsigned DivOp;
3981 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003982 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003983
3984 if (IsMips64) {
3985 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3986 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003987 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003988 } else {
3989 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3990 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003991 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003992 }
3993
3994 bool UseTraps = useTraps();
3995
Simon Dardis12850ee2017-01-31 10:49:24 +00003996 if (RtOp.isImm()) {
3997 unsigned ATReg = getATReg(IDLoc);
3998 if (!ATReg)
3999 return true;
4000
4001 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00004002 if (UseTraps)
4003 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
4004 else
4005 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4006 return false;
4007 }
4008
4009 if (ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004010 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00004011 return false;
4012 } else if (Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004013 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00004014 return false;
4015 } else {
4016 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
4017 false, Inst.getLoc(), Out, STI))
4018 return true;
4019 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
4020 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
4021 return false;
4022 }
4023 return true;
4024 }
4025
Simon Dardis509da1a2017-02-13 16:06:48 +00004026 // If the macro expansion of (d)div(u) would always trap or break, insert
4027 // the trap/break and exit. This gives a different result to GAS. GAS has
4028 // an inconsistency/missed optimization in that not all cases are handled
4029 // equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004030 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004031 if (UseTraps) {
4032 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004033 return false;
4034 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004035 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4036 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004037 }
4038
Simon Dardis509da1a2017-02-13 16:06:48 +00004039 // Temporary label for first branch traget
4040 MCContext &Context = TOut.getStreamer().getContext();
4041 MCSymbol *BrTarget;
4042 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004043
4044 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004045 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004046 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004047 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004048 BrTarget = Context.createTempSymbol();
4049 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4050 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004051 }
4052
Daniel Sandersa736b372016-04-29 13:33:12 +00004053 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004054
4055 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004056 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004057
4058 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004059 if (!UseTraps)
4060 TOut.getStreamer().EmitLabel(BrTarget);
4061
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004062 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004063 return false;
4064 }
4065
4066 unsigned ATReg = getATReg(IDLoc);
4067 if (!ATReg)
4068 return true;
4069
Simon Dardis509da1a2017-02-13 16:06:48 +00004070 if (!UseTraps)
4071 TOut.getStreamer().EmitLabel(BrTarget);
4072
Daniel Sandersa736b372016-04-29 13:33:12 +00004073 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004074
4075 // Temporary label for the second branch target.
4076 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4077 MCOperand LabelOpEnd =
4078 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4079
4080 // Branch to the mflo instruction.
4081 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4082
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004083 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004084 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
4085 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004086 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004087 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004088 }
4089
4090 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004091 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004092 else {
4093 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004094 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004095 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
4096 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004097 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004098
4099 TOut.getStreamer().EmitLabel(BrTargetEnd);
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004100 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004101 return false;
4102}
4103
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004104bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004105 SMLoc IDLoc, MCStreamer &Out,
4106 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004107 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004108
4109 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4110 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4111 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4112
4113 unsigned FirstReg = Inst.getOperand(0).getReg();
4114 unsigned SecondReg = Inst.getOperand(1).getReg();
4115 unsigned ThirdReg = Inst.getOperand(2).getReg();
4116
4117 if (hasMips1() && !hasMips2()) {
4118 unsigned ATReg = getATReg(IDLoc);
4119 if (!ATReg)
4120 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004121 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4122 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4123 TOut.emitNop(IDLoc, STI);
4124 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4125 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4126 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4127 TOut.emitNop(IDLoc, STI);
4128 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4129 : Mips::CVT_W_S,
4130 FirstReg, SecondReg, IDLoc, STI);
4131 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4132 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004133 return false;
4134 }
4135
Daniel Sandersa736b372016-04-29 13:33:12 +00004136 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4137 : Mips::TRUNC_W_S,
4138 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004139
4140 return false;
4141}
4142
Daniel Sanders6394ee52015-10-15 14:52:58 +00004143bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004144 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004145 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004146 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004147 }
4148
Toma Tabacud88d79c2015-06-23 14:39:42 +00004149 const MCOperand &DstRegOp = Inst.getOperand(0);
4150 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004151 const MCOperand &SrcRegOp = Inst.getOperand(1);
4152 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004153 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4154 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4155
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004156 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004157 unsigned DstReg = DstRegOp.getReg();
4158 unsigned SrcReg = SrcRegOp.getReg();
4159 int64_t OffsetValue = OffsetImmOp.getImm();
4160
4161 // NOTE: We always need AT for ULHU, as it is always used as the source
4162 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004163 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004164 unsigned ATReg = getATReg(IDLoc);
4165 if (!ATReg)
4166 return true;
4167
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004168 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4169 if (IsLargeOffset) {
4170 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4171 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004172 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004173 }
4174
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004175 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4176 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4177 if (isLittle())
4178 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004179
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004180 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4181 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004182
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004183 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4184 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004185
Daniel Sandersa736b372016-04-29 13:33:12 +00004186 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004187 FirstOffset, IDLoc, STI);
4188 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004189 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004190 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004191
4192 return false;
4193}
4194
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004195bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004196 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004197 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004198 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004199 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004200
4201 const MCOperand &DstRegOp = Inst.getOperand(0);
4202 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004203 const MCOperand &SrcRegOp = Inst.getOperand(1);
4204 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004205 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4206 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4207
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004208 MipsTargetStreamer &TOut = getTargetStreamer();
4209 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004210 unsigned SrcReg = SrcRegOp.getReg();
4211 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004212
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004213 warnIfNoMacro(IDLoc);
4214 unsigned ATReg = getATReg(IDLoc);
4215 if (!ATReg)
4216 return true;
4217
4218 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4219 if (IsLargeOffset) {
4220 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4221 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004222 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004223 }
4224
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004225 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4226 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4227 if (isLittle())
4228 std::swap(FirstOffset, SecondOffset);
4229
4230 if (IsLargeOffset) {
4231 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4232 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4233 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4234 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4235 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4236 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004237 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004238 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4239 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4240 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004241 }
4242
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004243 return false;
4244}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004245
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004246bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4247 const MCSubtargetInfo *STI) {
4248 if (hasMips32r6() || hasMips64r6()) {
4249 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4250 }
4251
4252 const MCOperand &DstRegOp = Inst.getOperand(0);
4253 assert(DstRegOp.isReg() && "expected register operand kind");
4254 const MCOperand &SrcRegOp = Inst.getOperand(1);
4255 assert(SrcRegOp.isReg() && "expected register operand kind");
4256 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4257 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4258
4259 MipsTargetStreamer &TOut = getTargetStreamer();
4260 unsigned DstReg = DstRegOp.getReg();
4261 unsigned SrcReg = SrcRegOp.getReg();
4262 int64_t OffsetValue = OffsetImmOp.getImm();
4263
4264 // Compute left/right load/store offsets.
4265 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4266 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4267 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4268 if (isLittle())
4269 std::swap(LxlOffset, LxrOffset);
4270
4271 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4272 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4273 unsigned TmpReg = SrcReg;
4274 if (IsLargeOffset || DoMove) {
4275 warnIfNoMacro(IDLoc);
4276 TmpReg = getATReg(IDLoc);
4277 if (!TmpReg)
4278 return true;
4279 }
4280
4281 if (IsLargeOffset) {
4282 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4283 IDLoc, Out, STI))
4284 return true;
4285 }
4286
4287 if (DoMove)
4288 std::swap(DstReg, TmpReg);
4289
4290 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4291 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4292 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4293 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4294
4295 if (DoMove)
4296 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004297
4298 return false;
4299}
4300
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004301bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004302 MCStreamer &Out,
4303 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004304 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004305
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004306 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4307 assert(Inst.getOperand(0).isReg() &&
4308 Inst.getOperand(1).isReg() &&
4309 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004310
4311 unsigned ATReg = Mips::NoRegister;
4312 unsigned FinalDstReg = Mips::NoRegister;
4313 unsigned DstReg = Inst.getOperand(0).getReg();
4314 unsigned SrcReg = Inst.getOperand(1).getReg();
4315 int64_t ImmValue = Inst.getOperand(2).getImm();
4316
Simon Dardisaa208812017-02-24 14:34:32 +00004317 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004318
4319 unsigned FinalOpcode = Inst.getOpcode();
4320
4321 if (DstReg == SrcReg) {
4322 ATReg = getATReg(Inst.getLoc());
4323 if (!ATReg)
4324 return true;
4325 FinalDstReg = DstReg;
4326 DstReg = ATReg;
4327 }
4328
Simon Atanasyan478220f2018-05-24 07:36:00 +00004329 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false,
4330 Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004331 switch (FinalOpcode) {
4332 default:
4333 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004334 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004335 FinalOpcode = Mips::ADD;
4336 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004337 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004338 FinalOpcode = Mips::ADDu;
4339 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004340 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004341 FinalOpcode = Mips::AND;
4342 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004343 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004344 FinalOpcode = Mips::NOR;
4345 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004346 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004347 FinalOpcode = Mips::OR;
4348 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004349 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004350 FinalOpcode = Mips::SLT;
4351 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004352 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004353 FinalOpcode = Mips::SLTu;
4354 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004355 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004356 FinalOpcode = Mips::XOR;
4357 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004358 case Mips::ADDi_MM:
4359 FinalOpcode = Mips::ADD_MM;
4360 break;
4361 case Mips::ADDiu_MM:
4362 FinalOpcode = Mips::ADDu_MM;
4363 break;
4364 case Mips::ANDi_MM:
4365 FinalOpcode = Mips::AND_MM;
4366 break;
4367 case Mips::ORi_MM:
4368 FinalOpcode = Mips::OR_MM;
4369 break;
4370 case Mips::SLTi_MM:
4371 FinalOpcode = Mips::SLT_MM;
4372 break;
4373 case Mips::SLTiu_MM:
4374 FinalOpcode = Mips::SLTu_MM;
4375 break;
4376 case Mips::XORi_MM:
4377 FinalOpcode = Mips::XOR_MM;
4378 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004379 case Mips::ANDi64:
4380 FinalOpcode = Mips::AND64;
4381 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004382 case Mips::NORImm64:
4383 FinalOpcode = Mips::NOR64;
4384 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004385 case Mips::ORi64:
4386 FinalOpcode = Mips::OR64;
4387 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004388 case Mips::SLTImm64:
4389 FinalOpcode = Mips::SLT64;
4390 break;
4391 case Mips::SLTUImm64:
4392 FinalOpcode = Mips::SLTu64;
4393 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004394 case Mips::XORi64:
4395 FinalOpcode = Mips::XOR64;
4396 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004397 }
4398
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004399 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004400 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004401 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004402 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004403 return false;
4404 }
4405 return true;
4406}
4407
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004408bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4409 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004410 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004411 unsigned ATReg = Mips::NoRegister;
4412 unsigned DReg = Inst.getOperand(0).getReg();
4413 unsigned SReg = Inst.getOperand(1).getReg();
4414 unsigned TReg = Inst.getOperand(2).getReg();
4415 unsigned TmpReg = DReg;
4416
4417 unsigned FirstShift = Mips::NOP;
4418 unsigned SecondShift = Mips::NOP;
4419
4420 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004421 if (DReg == SReg) {
4422 TmpReg = getATReg(Inst.getLoc());
4423 if (!TmpReg)
4424 return true;
4425 }
4426
4427 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004428 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4429 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004430 return false;
4431 }
4432
4433 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004434 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004435 return false;
4436 }
4437
4438 return true;
4439 }
4440
4441 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004442 switch (Inst.getOpcode()) {
4443 default:
4444 llvm_unreachable("unexpected instruction opcode");
4445 case Mips::ROL:
4446 FirstShift = Mips::SRLV;
4447 SecondShift = Mips::SLLV;
4448 break;
4449 case Mips::ROR:
4450 FirstShift = Mips::SLLV;
4451 SecondShift = Mips::SRLV;
4452 break;
4453 }
4454
4455 ATReg = getATReg(Inst.getLoc());
4456 if (!ATReg)
4457 return true;
4458
Daniel Sandersa736b372016-04-29 13:33:12 +00004459 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4460 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4461 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4462 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004463
4464 return false;
4465 }
4466
4467 return true;
4468}
4469
4470bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004471 MCStreamer &Out,
4472 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004473 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004474 unsigned ATReg = Mips::NoRegister;
4475 unsigned DReg = Inst.getOperand(0).getReg();
4476 unsigned SReg = Inst.getOperand(1).getReg();
4477 int64_t ImmValue = Inst.getOperand(2).getImm();
4478
4479 unsigned FirstShift = Mips::NOP;
4480 unsigned SecondShift = Mips::NOP;
4481
4482 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004483 if (Inst.getOpcode() == Mips::ROLImm) {
4484 uint64_t MaxShift = 32;
4485 uint64_t ShiftValue = ImmValue;
4486 if (ImmValue != 0)
4487 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004488 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004489 return false;
4490 }
4491
4492 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004493 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004494 return false;
4495 }
4496
4497 return true;
4498 }
4499
4500 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004501 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004502 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004503 return false;
4504 }
4505
4506 switch (Inst.getOpcode()) {
4507 default:
4508 llvm_unreachable("unexpected instruction opcode");
4509 case Mips::ROLImm:
4510 FirstShift = Mips::SLL;
4511 SecondShift = Mips::SRL;
4512 break;
4513 case Mips::RORImm:
4514 FirstShift = Mips::SRL;
4515 SecondShift = Mips::SLL;
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.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4524 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4525 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004526
4527 return false;
4528 }
4529
4530 return true;
4531}
4532
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004533bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4534 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004535 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004536 unsigned ATReg = Mips::NoRegister;
4537 unsigned DReg = Inst.getOperand(0).getReg();
4538 unsigned SReg = Inst.getOperand(1).getReg();
4539 unsigned TReg = Inst.getOperand(2).getReg();
4540 unsigned TmpReg = DReg;
4541
4542 unsigned FirstShift = Mips::NOP;
4543 unsigned SecondShift = Mips::NOP;
4544
4545 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004546 if (TmpReg == SReg) {
4547 TmpReg = getATReg(Inst.getLoc());
4548 if (!TmpReg)
4549 return true;
4550 }
4551
4552 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004553 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4554 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004555 return false;
4556 }
4557
4558 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004559 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004560 return false;
4561 }
4562
4563 return true;
4564 }
4565
4566 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004567 switch (Inst.getOpcode()) {
4568 default:
4569 llvm_unreachable("unexpected instruction opcode");
4570 case Mips::DROL:
4571 FirstShift = Mips::DSRLV;
4572 SecondShift = Mips::DSLLV;
4573 break;
4574 case Mips::DROR:
4575 FirstShift = Mips::DSLLV;
4576 SecondShift = Mips::DSRLV;
4577 break;
4578 }
4579
4580 ATReg = getATReg(Inst.getLoc());
4581 if (!ATReg)
4582 return true;
4583
Daniel Sandersa736b372016-04-29 13:33:12 +00004584 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4585 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4586 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4587 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004588
4589 return false;
4590 }
4591
4592 return true;
4593}
4594
4595bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004596 MCStreamer &Out,
4597 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004598 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004599 unsigned ATReg = Mips::NoRegister;
4600 unsigned DReg = Inst.getOperand(0).getReg();
4601 unsigned SReg = Inst.getOperand(1).getReg();
4602 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4603
4604 unsigned FirstShift = Mips::NOP;
4605 unsigned SecondShift = Mips::NOP;
4606
4607 MCInst TmpInst;
4608
4609 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004610 unsigned FinalOpcode = Mips::NOP;
4611 if (ImmValue == 0)
4612 FinalOpcode = Mips::DROTR;
4613 else if (ImmValue % 32 == 0)
4614 FinalOpcode = Mips::DROTR32;
4615 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4616 if (Inst.getOpcode() == Mips::DROLImm)
4617 FinalOpcode = Mips::DROTR32;
4618 else
4619 FinalOpcode = Mips::DROTR;
4620 } else if (ImmValue >= 33) {
4621 if (Inst.getOpcode() == Mips::DROLImm)
4622 FinalOpcode = Mips::DROTR;
4623 else
4624 FinalOpcode = Mips::DROTR32;
4625 }
4626
4627 uint64_t ShiftValue = ImmValue % 32;
4628 if (Inst.getOpcode() == Mips::DROLImm)
4629 ShiftValue = (32 - ImmValue % 32) % 32;
4630
Daniel Sandersa736b372016-04-29 13:33:12 +00004631 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004632
4633 return false;
4634 }
4635
4636 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004637 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004638 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004639 return false;
4640 }
4641
4642 switch (Inst.getOpcode()) {
4643 default:
4644 llvm_unreachable("unexpected instruction opcode");
4645 case Mips::DROLImm:
4646 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4647 FirstShift = Mips::DSLL;
4648 SecondShift = Mips::DSRL32;
4649 }
4650 if (ImmValue == 32) {
4651 FirstShift = Mips::DSLL32;
4652 SecondShift = Mips::DSRL32;
4653 }
4654 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4655 FirstShift = Mips::DSLL32;
4656 SecondShift = Mips::DSRL;
4657 }
4658 break;
4659 case Mips::DRORImm:
4660 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4661 FirstShift = Mips::DSRL;
4662 SecondShift = Mips::DSLL32;
4663 }
4664 if (ImmValue == 32) {
4665 FirstShift = Mips::DSRL32;
4666 SecondShift = Mips::DSLL32;
4667 }
4668 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4669 FirstShift = Mips::DSRL32;
4670 SecondShift = Mips::DSLL;
4671 }
4672 break;
4673 }
4674
4675 ATReg = getATReg(Inst.getLoc());
4676 if (!ATReg)
4677 return true;
4678
Daniel Sandersa736b372016-04-29 13:33:12 +00004679 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4680 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4681 Inst.getLoc(), STI);
4682 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004683
4684 return false;
4685 }
4686
4687 return true;
4688}
4689
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004690bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4691 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004692 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004693 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4694 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4695
Daniel Sandersa736b372016-04-29 13:33:12 +00004696 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004697 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004698 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004699 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004700 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4701 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004702
4703 return false;
4704}
4705
Simon Dardis3c82a642017-02-08 16:25:05 +00004706bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4707 const MCSubtargetInfo *STI) {
4708 MipsTargetStreamer &TOut = getTargetStreamer();
4709 unsigned ATReg = Mips::NoRegister;
4710 unsigned DstReg = Inst.getOperand(0).getReg();
4711 unsigned SrcReg = Inst.getOperand(1).getReg();
4712 int32_t ImmValue = Inst.getOperand(2).getImm();
4713
4714 ATReg = getATReg(IDLoc);
4715 if (!ATReg)
4716 return true;
4717
Simon Atanasyan478220f2018-05-24 07:36:00 +00004718 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out,
4719 STI);
Simon Dardis3c82a642017-02-08 16:25:05 +00004720
4721 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4722 SrcReg, ATReg, IDLoc, STI);
4723
4724 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4725
4726 return false;
4727}
4728
4729bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4730 const MCSubtargetInfo *STI) {
4731 MipsTargetStreamer &TOut = getTargetStreamer();
4732 unsigned ATReg = Mips::NoRegister;
4733 unsigned DstReg = Inst.getOperand(0).getReg();
4734 unsigned SrcReg = Inst.getOperand(1).getReg();
4735 unsigned TmpReg = Inst.getOperand(2).getReg();
4736
4737 ATReg = getATReg(Inst.getLoc());
4738 if (!ATReg)
4739 return true;
4740
4741 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4742 SrcReg, TmpReg, IDLoc, STI);
4743
4744 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4745
4746 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4747 DstReg, DstReg, 0x1F, IDLoc, STI);
4748
4749 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4750
4751 if (useTraps()) {
4752 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4753 } else {
4754 MCContext & Context = TOut.getStreamer().getContext();
4755 MCSymbol * BrTarget = Context.createTempSymbol();
4756 MCOperand LabelOp =
4757 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4758
4759 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4760 if (AssemblerOptions.back()->isReorder())
4761 TOut.emitNop(IDLoc, STI);
4762 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4763
4764 TOut.getStreamer().EmitLabel(BrTarget);
4765 }
4766 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4767
4768 return false;
4769}
4770
4771bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4772 const MCSubtargetInfo *STI) {
4773 MipsTargetStreamer &TOut = getTargetStreamer();
4774 unsigned ATReg = Mips::NoRegister;
4775 unsigned DstReg = Inst.getOperand(0).getReg();
4776 unsigned SrcReg = Inst.getOperand(1).getReg();
4777 unsigned TmpReg = Inst.getOperand(2).getReg();
4778
4779 ATReg = getATReg(IDLoc);
4780 if (!ATReg)
4781 return true;
4782
4783 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4784 SrcReg, TmpReg, IDLoc, STI);
4785
4786 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4787 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4788 if (useTraps()) {
4789 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4790 } else {
4791 MCContext & Context = TOut.getStreamer().getContext();
4792 MCSymbol * BrTarget = Context.createTempSymbol();
4793 MCOperand LabelOp =
4794 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4795
4796 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4797 if (AssemblerOptions.back()->isReorder())
4798 TOut.emitNop(IDLoc, STI);
4799 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4800
4801 TOut.getStreamer().EmitLabel(BrTarget);
4802 }
4803
4804 return false;
4805}
4806
4807bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4808 const MCSubtargetInfo *STI) {
4809 MipsTargetStreamer &TOut = getTargetStreamer();
4810 unsigned DstReg = Inst.getOperand(0).getReg();
4811 unsigned SrcReg = Inst.getOperand(1).getReg();
4812 unsigned TmpReg = Inst.getOperand(2).getReg();
4813
4814 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4815 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4816
4817 return false;
4818}
4819
Simon Dardisaff4d142016-10-18 14:28:00 +00004820// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4821// lw $<reg+1>>, offset+4($reg2)'
4822// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4823// sw $<reg+1>>, offset+4($reg2)'
4824// for O32.
4825bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4826 MCStreamer &Out,
4827 const MCSubtargetInfo *STI,
4828 bool IsLoad) {
4829 if (!isABI_O32())
4830 return true;
4831
4832 warnIfNoMacro(IDLoc);
4833
4834 MipsTargetStreamer &TOut = getTargetStreamer();
4835 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4836 unsigned FirstReg = Inst.getOperand(0).getReg();
4837 unsigned SecondReg = nextReg(FirstReg);
4838 unsigned BaseReg = Inst.getOperand(1).getReg();
4839 if (!SecondReg)
4840 return true;
4841
4842 warnIfRegIndexIsAT(FirstReg, IDLoc);
4843
4844 assert(Inst.getOperand(2).isImm() &&
4845 "Offset for load macro is not immediate!");
4846
4847 MCOperand &FirstOffset = Inst.getOperand(2);
4848 signed NextOffset = FirstOffset.getImm() + 4;
4849 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4850
4851 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4852 return true;
4853
4854 // For loads, clobber the base register with the second load instead of the
4855 // first if the BaseReg == FirstReg.
4856 if (FirstReg != BaseReg || !IsLoad) {
4857 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4858 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4859 } else {
4860 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4861 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4862 }
4863
4864 return false;
4865}
4866
Simon Dardis43115a12016-11-21 20:30:41 +00004867bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4868 const MCSubtargetInfo *STI) {
4869
4870 warnIfNoMacro(IDLoc);
4871 MipsTargetStreamer &TOut = getTargetStreamer();
4872
4873 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4874 Inst.getOperand(2).getReg() != Mips::ZERO) {
4875 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4876 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4877 IDLoc, STI);
4878 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4879 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4880 return false;
4881 }
4882
4883 unsigned Reg = 0;
4884 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4885 Reg = Inst.getOperand(2).getReg();
4886 } else {
4887 Reg = Inst.getOperand(1).getReg();
4888 }
4889 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4890 return false;
4891}
4892
4893bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4894 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004895 warnIfNoMacro(IDLoc);
4896 MipsTargetStreamer &TOut = getTargetStreamer();
4897
4898 unsigned Opc;
4899 int64_t Imm = Inst.getOperand(2).getImm();
4900 unsigned Reg = Inst.getOperand(1).getReg();
4901
4902 if (Imm == 0) {
4903 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4904 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4905 return false;
4906 } else {
4907
4908 if (Reg == Mips::ZERO) {
4909 Warning(IDLoc, "comparison is always false");
4910 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4911 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4912 return false;
4913 }
4914
4915 if (Imm > -0x8000 && Imm < 0) {
4916 Imm = -Imm;
4917 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4918 } else {
4919 Opc = Mips::XORi;
4920 }
4921 }
4922 if (!isUInt<16>(Imm)) {
4923 unsigned ATReg = getATReg(IDLoc);
4924 if (!ATReg)
4925 return true;
4926
4927 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4928 Out, STI))
4929 return true;
4930
4931 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4932 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4933 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4934 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4935 return false;
4936 }
4937
4938 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4939 Imm, IDLoc, STI);
4940 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4941 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4942 return false;
4943}
4944
Simon Dardisde5ed0c2017-11-14 22:26:42 +00004945// Map the DSP accumulator and control register to the corresponding gpr
4946// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
4947// do not map the DSP registers contigously to gpr registers.
4948static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
4949 switch (Inst.getOpcode()) {
4950 case Mips::MFTLO:
4951 case Mips::MTTLO:
4952 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4953 case Mips::AC0:
4954 return Mips::ZERO;
4955 case Mips::AC1:
4956 return Mips::A0;
4957 case Mips::AC2:
4958 return Mips::T0;
4959 case Mips::AC3:
4960 return Mips::T4;
4961 default:
4962 llvm_unreachable("Unknown register for 'mttr' alias!");
4963 }
4964 case Mips::MFTHI:
4965 case Mips::MTTHI:
4966 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4967 case Mips::AC0:
4968 return Mips::AT;
4969 case Mips::AC1:
4970 return Mips::A1;
4971 case Mips::AC2:
4972 return Mips::T1;
4973 case Mips::AC3:
4974 return Mips::T5;
4975 default:
4976 llvm_unreachable("Unknown register for 'mttr' alias!");
4977 }
4978 case Mips::MFTACX:
4979 case Mips::MTTACX:
4980 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4981 case Mips::AC0:
4982 return Mips::V0;
4983 case Mips::AC1:
4984 return Mips::A2;
4985 case Mips::AC2:
4986 return Mips::T2;
4987 case Mips::AC3:
4988 return Mips::T6;
4989 default:
4990 llvm_unreachable("Unknown register for 'mttr' alias!");
4991 }
4992 case Mips::MFTDSP:
4993 case Mips::MTTDSP:
4994 return Mips::S0;
4995 default:
4996 llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
4997 }
4998}
4999
5000// Map the floating point register operand to the corresponding register
5001// operand.
5002static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
5003 switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
5004 case Mips::F0: return Mips::ZERO;
5005 case Mips::F1: return Mips::AT;
5006 case Mips::F2: return Mips::V0;
5007 case Mips::F3: return Mips::V1;
5008 case Mips::F4: return Mips::A0;
5009 case Mips::F5: return Mips::A1;
5010 case Mips::F6: return Mips::A2;
5011 case Mips::F7: return Mips::A3;
5012 case Mips::F8: return Mips::T0;
5013 case Mips::F9: return Mips::T1;
5014 case Mips::F10: return Mips::T2;
5015 case Mips::F11: return Mips::T3;
5016 case Mips::F12: return Mips::T4;
5017 case Mips::F13: return Mips::T5;
5018 case Mips::F14: return Mips::T6;
5019 case Mips::F15: return Mips::T7;
5020 case Mips::F16: return Mips::S0;
5021 case Mips::F17: return Mips::S1;
5022 case Mips::F18: return Mips::S2;
5023 case Mips::F19: return Mips::S3;
5024 case Mips::F20: return Mips::S4;
5025 case Mips::F21: return Mips::S5;
5026 case Mips::F22: return Mips::S6;
5027 case Mips::F23: return Mips::S7;
5028 case Mips::F24: return Mips::T8;
5029 case Mips::F25: return Mips::T9;
5030 case Mips::F26: return Mips::K0;
5031 case Mips::F27: return Mips::K1;
5032 case Mips::F28: return Mips::GP;
5033 case Mips::F29: return Mips::SP;
5034 case Mips::F30: return Mips::FP;
5035 case Mips::F31: return Mips::RA;
5036 default: llvm_unreachable("Unknown register for mttc1 alias!");
5037 }
5038}
5039
5040// Map the coprocessor operand the corresponding gpr register operand.
5041static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
5042 switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
5043 case Mips::COP00: return Mips::ZERO;
5044 case Mips::COP01: return Mips::AT;
5045 case Mips::COP02: return Mips::V0;
5046 case Mips::COP03: return Mips::V1;
5047 case Mips::COP04: return Mips::A0;
5048 case Mips::COP05: return Mips::A1;
5049 case Mips::COP06: return Mips::A2;
5050 case Mips::COP07: return Mips::A3;
5051 case Mips::COP08: return Mips::T0;
5052 case Mips::COP09: return Mips::T1;
5053 case Mips::COP010: return Mips::T2;
5054 case Mips::COP011: return Mips::T3;
5055 case Mips::COP012: return Mips::T4;
5056 case Mips::COP013: return Mips::T5;
5057 case Mips::COP014: return Mips::T6;
5058 case Mips::COP015: return Mips::T7;
5059 case Mips::COP016: return Mips::S0;
5060 case Mips::COP017: return Mips::S1;
5061 case Mips::COP018: return Mips::S2;
5062 case Mips::COP019: return Mips::S3;
5063 case Mips::COP020: return Mips::S4;
5064 case Mips::COP021: return Mips::S5;
5065 case Mips::COP022: return Mips::S6;
5066 case Mips::COP023: return Mips::S7;
5067 case Mips::COP024: return Mips::T8;
5068 case Mips::COP025: return Mips::T9;
5069 case Mips::COP026: return Mips::K0;
5070 case Mips::COP027: return Mips::K1;
5071 case Mips::COP028: return Mips::GP;
5072 case Mips::COP029: return Mips::SP;
5073 case Mips::COP030: return Mips::FP;
5074 case Mips::COP031: return Mips::RA;
5075 default: llvm_unreachable("Unknown register for mttc0 alias!");
5076 }
5077}
5078
5079/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
5080/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
5081bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5082 const MCSubtargetInfo *STI) {
5083 MipsTargetStreamer &TOut = getTargetStreamer();
5084 unsigned rd = 0;
5085 unsigned u = 1;
5086 unsigned sel = 0;
5087 unsigned h = 0;
5088 bool IsMFTR = false;
5089 switch (Inst.getOpcode()) {
5090 case Mips::MFTC0:
5091 IsMFTR = true;
5092 LLVM_FALLTHROUGH;
5093 case Mips::MTTC0:
5094 u = 0;
5095 rd = getRegisterForMxtrC0(Inst, IsMFTR);
5096 sel = Inst.getOperand(2).getImm();
5097 break;
5098 case Mips::MFTGPR:
5099 IsMFTR = true;
5100 LLVM_FALLTHROUGH;
5101 case Mips::MTTGPR:
5102 rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
5103 break;
5104 case Mips::MFTLO:
5105 case Mips::MFTHI:
5106 case Mips::MFTACX:
5107 case Mips::MFTDSP:
5108 IsMFTR = true;
5109 LLVM_FALLTHROUGH;
5110 case Mips::MTTLO:
5111 case Mips::MTTHI:
5112 case Mips::MTTACX:
5113 case Mips::MTTDSP:
5114 rd = getRegisterForMxtrDSP(Inst, IsMFTR);
5115 sel = 1;
5116 break;
5117 case Mips::MFTHC1:
5118 h = 1;
5119 LLVM_FALLTHROUGH;
5120 case Mips::MFTC1:
5121 IsMFTR = true;
5122 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5123 sel = 2;
5124 break;
5125 case Mips::MTTHC1:
5126 h = 1;
5127 LLVM_FALLTHROUGH;
5128 case Mips::MTTC1:
5129 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5130 sel = 2;
5131 break;
5132 case Mips::CFTC1:
5133 IsMFTR = true;
5134 LLVM_FALLTHROUGH;
5135 case Mips::CTTC1:
5136 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5137 sel = 3;
5138 break;
5139 }
5140 unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
5141 unsigned Op1 =
5142 IsMFTR ? rd
5143 : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
5144 : Inst.getOperand(0).getReg());
5145
5146 TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
5147 STI);
5148 return false;
5149}
5150
Daniel Sandersc5537422016-07-27 13:49:44 +00005151unsigned
5152MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
5153 const OperandVector &Operands) {
5154 switch (Inst.getOpcode()) {
5155 default:
5156 return Match_Success;
5157 case Mips::DATI:
5158 case Mips::DAHI:
Daniel Sandersb23005e2016-07-28 15:59:06 +00005159 if (static_cast<MipsOperand &>(*Operands[1])
5160 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
5161 return Match_Success;
5162 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00005163 }
5164}
Simon Dardis730fdb72017-01-16 13:55:58 +00005165
Matheus Almeida595fcab2014-06-11 15:05:56 +00005166unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00005167 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00005168 // As described by the MIPSR6 spec, daui must not use the zero operand for
5169 // its source operand.
5170 case Mips::DAUI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00005171 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5172 Inst.getOperand(1).getReg() == Mips::ZERO_64)
5173 return Match_RequiresNoZeroRegister;
5174 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00005175 // As described by the Mips32r2 spec, the registers Rd and Rs for
5176 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00005177 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00005178 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00005179 case Mips::JALR_HB:
Simon Dardis7bc8ad52018-02-21 00:06:53 +00005180 case Mips::JALR_HB64:
Simon Dardisb60833c2016-05-31 17:34:42 +00005181 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00005182 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00005183 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5184 return Match_RequiresDifferentSrcAndDst;
5185 return Match_Success;
5186 case Mips::LWP_MM:
Simon Dardisb60833c2016-05-31 17:34:42 +00005187 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
5188 return Match_RequiresDifferentSrcAndDst;
5189 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00005190 case Mips::SYNC:
5191 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
5192 return Match_NonZeroOperandForSync;
5193 return Match_Success;
Simon Dardis52ae4f02018-03-07 11:39:48 +00005194 case Mips::MFC0:
5195 case Mips::MTC0:
5196 case Mips::MTC2:
5197 case Mips::MFC2:
5198 if (Inst.getOperand(2).getImm() != 0 && !hasMips32())
5199 return Match_NonZeroOperandForMTCX;
5200 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005201 // As described the MIPSR6 spec, the compact branches that compare registers
5202 // must:
5203 // a) Not use the zero register.
5204 // b) Not use the same register twice.
5205 // c) rs < rt for bnec, beqc.
5206 // NB: For this case, the encoding will swap the operands as their
5207 // ordering doesn't matter. GAS performs this transformation too.
5208 // Hence, that constraint does not have to be enforced.
5209 //
5210 // The compact branches that branch iff the signed addition of two registers
5211 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
5212 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005213 case Mips::BLEZC: case Mips::BLEZC_MMR6:
5214 case Mips::BGEZC: case Mips::BGEZC_MMR6:
5215 case Mips::BGTZC: case Mips::BGTZC_MMR6:
5216 case Mips::BLTZC: case Mips::BLTZC_MMR6:
5217 case Mips::BEQZC: case Mips::BEQZC_MMR6:
5218 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005219 case Mips::BLEZC64:
5220 case Mips::BGEZC64:
5221 case Mips::BGTZC64:
5222 case Mips::BLTZC64:
5223 case Mips::BEQZC64:
5224 case Mips::BNEZC64:
5225 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5226 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005227 return Match_RequiresNoZeroRegister;
5228 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005229 case Mips::BGEC: case Mips::BGEC_MMR6:
5230 case Mips::BLTC: case Mips::BLTC_MMR6:
5231 case Mips::BGEUC: case Mips::BGEUC_MMR6:
5232 case Mips::BLTUC: case Mips::BLTUC_MMR6:
5233 case Mips::BEQC: case Mips::BEQC_MMR6:
5234 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005235 case Mips::BGEC64:
5236 case Mips::BLTC64:
5237 case Mips::BGEUC64:
5238 case Mips::BLTUC64:
5239 case Mips::BEQC64:
5240 case Mips::BNEC64:
5241 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5242 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005243 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00005244 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5245 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005246 return Match_RequiresNoZeroRegister;
5247 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5248 return Match_RequiresDifferentOperands;
5249 return Match_Success;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005250 case Mips::DINS: {
Simon Dardis55e44672017-09-14 17:27:53 +00005251 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5252 "Operands must be immediates for dins!");
5253 const signed Pos = Inst.getOperand(2).getImm();
5254 const signed Size = Inst.getOperand(3).getImm();
5255 if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
5256 return Match_RequiresPosSizeRange0_32;
5257 return Match_Success;
5258 }
5259 case Mips::DINSM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005260 case Mips::DINSU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005261 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5262 "Operands must be immediates for dinsm/dinsu!");
5263 const signed Pos = Inst.getOperand(2).getImm();
5264 const signed Size = Inst.getOperand(3).getImm();
5265 if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
5266 return Match_RequiresPosSizeRange33_64;
5267 return Match_Success;
5268 }
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005269 case Mips::DEXT: {
Simon Dardis55e44672017-09-14 17:27:53 +00005270 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5271 "Operands must be immediates for DEXTM!");
5272 const signed Pos = Inst.getOperand(2).getImm();
5273 const signed Size = Inst.getOperand(3).getImm();
5274 if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
5275 return Match_RequiresPosSizeUImm6;
5276 return Match_Success;
5277 }
5278 case Mips::DEXTM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005279 case Mips::DEXTU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005280 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5281 "Operands must be immediates for dextm/dextu!");
5282 const signed Pos = Inst.getOperand(2).getImm();
5283 const signed Size = Inst.getOperand(3).getImm();
5284 if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
5285 return Match_RequiresPosSizeRange33_64;
5286 return Match_Success;
5287 }
Petar Jovanovic3408caf2018-03-14 14:13:31 +00005288 case Mips::CRC32B: case Mips::CRC32CB:
5289 case Mips::CRC32H: case Mips::CRC32CH:
5290 case Mips::CRC32W: case Mips::CRC32CW:
5291 case Mips::CRC32D: case Mips::CRC32CD:
5292 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())
5293 return Match_RequiresSameSrcAndDst;
5294 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005295 }
Simon Dardis730fdb72017-01-16 13:55:58 +00005296
5297 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
5298 if ((TSFlags & MipsII::HasFCCRegOperand) &&
5299 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
5300 return Match_NoFCCRegisterForCurrentISA;
5301
5302 return Match_Success;
5303
Matheus Almeida595fcab2014-06-11 15:05:56 +00005304}
5305
Daniel Sanders52da7af2015-11-06 12:11:03 +00005306static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
5307 uint64_t ErrorInfo) {
5308 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
5309 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
5310 if (ErrorLoc == SMLoc())
5311 return Loc;
5312 return ErrorLoc;
5313 }
5314 return Loc;
5315}
5316
David Blaikie960ea3f2014-06-08 16:18:35 +00005317bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5318 OperandVector &Operands,
5319 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005320 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005321 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005322 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005323 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005324 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005325
5326 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005327 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005328 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005329 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005330 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005331 case Match_MissingFeature:
5332 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5333 return true;
5334 case Match_InvalidOperand: {
5335 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005336 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005337 if (ErrorInfo >= Operands.size())
5338 return Error(IDLoc, "too few operands for instruction");
5339
Daniel Sanders52da7af2015-11-06 12:11:03 +00005340 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005341 if (ErrorLoc == SMLoc())
5342 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005343 }
5344
5345 return Error(ErrorLoc, "invalid operand for instruction");
5346 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005347 case Match_NonZeroOperandForSync:
Simon Atanasyan478220f2018-05-24 07:36:00 +00005348 return Error(IDLoc,
5349 "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Simon Dardis52ae4f02018-03-07 11:39:48 +00005350 case Match_NonZeroOperandForMTCX:
5351 return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005352 case Match_MnemonicFail:
5353 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005354 case Match_RequiresDifferentSrcAndDst:
5355 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005356 case Match_RequiresDifferentOperands:
5357 return Error(IDLoc, "registers must be different");
5358 case Match_RequiresNoZeroRegister:
5359 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005360 case Match_RequiresSameSrcAndDst:
5361 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005362 case Match_NoFCCRegisterForCurrentISA:
5363 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5364 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005365 case Match_Immz:
5366 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005367 case Match_UImm1_0:
5368 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5369 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005370 case Match_UImm2_0:
5371 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5372 "expected 2-bit unsigned immediate");
5373 case Match_UImm2_1:
5374 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5375 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005376 case Match_UImm3_0:
5377 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5378 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005379 case Match_UImm4_0:
5380 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5381 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005382 case Match_SImm4_0:
5383 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5384 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005385 case Match_UImm5_0:
5386 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5387 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005388 case Match_SImm5_0:
5389 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5390 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005391 case Match_UImm5_1:
5392 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5393 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005394 case Match_UImm5_32:
5395 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5396 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005397 case Match_UImm5_33:
5398 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5399 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005400 case Match_UImm5_0_Report_UImm6:
5401 // This is used on UImm5 operands that have a corresponding UImm5_32
5402 // operand to avoid confusing the user.
5403 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5404 "expected 6-bit unsigned immediate");
5405 case Match_UImm5_Lsl2:
5406 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5407 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005408 case Match_UImmRange2_64:
5409 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5410 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005411 case Match_UImm6_0:
5412 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5413 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005414 case Match_UImm6_Lsl2:
5415 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5416 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005417 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005418 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5419 "expected 6-bit signed immediate");
5420 case Match_UImm7_0:
5421 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5422 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005423 case Match_UImm7_N1:
5424 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5425 "expected immediate in range -1 .. 126");
5426 case Match_SImm7_Lsl2:
5427 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5428 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005429 case Match_UImm8_0:
5430 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5431 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005432 case Match_UImm10_0:
5433 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5434 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005435 case Match_SImm10_0:
5436 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5437 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005438 case Match_SImm11_0:
5439 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5440 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005441 case Match_UImm16:
5442 case Match_UImm16_Relaxed:
Petar Jovanovice4dacb72017-09-12 21:43:33 +00005443 case Match_UImm16_AltRelaxed:
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005444 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5445 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005446 case Match_SImm16:
5447 case Match_SImm16_Relaxed:
5448 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5449 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005450 case Match_SImm19_Lsl2:
5451 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5452 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005453 case Match_UImm20_0:
5454 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5455 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005456 case Match_UImm26_0:
5457 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5458 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005459 case Match_SImm32:
5460 case Match_SImm32_Relaxed:
5461 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5462 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005463 case Match_UImm32_Coerced:
5464 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5465 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005466 case Match_MemSImm9:
5467 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5468 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005469 case Match_MemSImm10:
5470 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5471 "expected memory with 10-bit signed offset");
5472 case Match_MemSImm10Lsl1:
5473 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5474 "expected memory with 11-bit signed offset and multiple of 2");
5475 case Match_MemSImm10Lsl2:
5476 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5477 "expected memory with 12-bit signed offset and multiple of 4");
5478 case Match_MemSImm10Lsl3:
5479 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5480 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005481 case Match_MemSImm11:
5482 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5483 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005484 case Match_MemSImm12:
5485 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5486 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005487 case Match_MemSImm16:
5488 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5489 "expected memory with 16-bit signed offset");
Simon Atanasyand4d892f2018-04-26 19:55:28 +00005490 case Match_MemSImmPtr:
5491 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5492 "expected memory with 32-bit signed offset");
Simon Dardis6f83ae32017-09-14 15:17:50 +00005493 case Match_RequiresPosSizeRange0_32: {
5494 SMLoc ErrorStart = Operands[3]->getStartLoc();
5495 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5496 return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
5497 SMRange(ErrorStart, ErrorEnd));
5498 }
Simon Dardis55e44672017-09-14 17:27:53 +00005499 case Match_RequiresPosSizeUImm6: {
5500 SMLoc ErrorStart = Operands[3]->getStartLoc();
5501 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5502 return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
5503 SMRange(ErrorStart, ErrorEnd));
5504 }
Simon Dardis6f83ae32017-09-14 15:17:50 +00005505 case Match_RequiresPosSizeRange33_64: {
5506 SMLoc ErrorStart = Operands[3]->getStartLoc();
5507 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5508 return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
5509 SMRange(ErrorStart, ErrorEnd));
5510 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005511 }
Craig Topper589ceee2015-01-03 08:16:34 +00005512
5513 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005514}
5515
Toma Tabacud9d344b2015-04-27 14:05:04 +00005516void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5517 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5518 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5519 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005520}
5521
Toma Tabacu81496c12015-05-20 08:54:45 +00005522void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5523 if (!AssemblerOptions.back()->isMacro())
5524 Warning(Loc, "macro instruction expanded into multiple instructions");
5525}
5526
Simon Dardis6a319922018-05-25 16:15:48 +00005527void MipsAsmParser::ConvertXWPOperands(MCInst &Inst,
5528 const OperandVector &Operands) {
5529 assert(
5530 (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) &&
5531 "Unexpected instruction!");
5532 ((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, 1);
5533 int NextReg = nextReg(((MipsOperand &)*Operands[1]).getGPR32Reg());
5534 Inst.addOperand(MCOperand::createReg(NextReg));
5535 ((MipsOperand &)*Operands[2]).addMemOperands(Inst, 2);
5536}
5537
Daniel Sandersef638fe2014-10-03 15:37:37 +00005538void
5539MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5540 SMRange Range, bool ShowColors) {
5541 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005542 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005543 ShowColors);
5544}
5545
Jack Carter1ac53222013-02-20 23:11:17 +00005546int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005547 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005548
Vladimir Medic4c299852013-11-06 11:27:05 +00005549 CC = StringSwitch<unsigned>(Name)
5550 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005551 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005552 .Case("a0", 4)
5553 .Case("a1", 5)
5554 .Case("a2", 6)
5555 .Case("a3", 7)
5556 .Case("v0", 2)
5557 .Case("v1", 3)
5558 .Case("s0", 16)
5559 .Case("s1", 17)
5560 .Case("s2", 18)
5561 .Case("s3", 19)
5562 .Case("s4", 20)
5563 .Case("s5", 21)
5564 .Case("s6", 22)
5565 .Case("s7", 23)
5566 .Case("k0", 26)
5567 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005568 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005569 .Case("sp", 29)
5570 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005571 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005572 .Case("ra", 31)
5573 .Case("t0", 8)
5574 .Case("t1", 9)
5575 .Case("t2", 10)
5576 .Case("t3", 11)
5577 .Case("t4", 12)
5578 .Case("t5", 13)
5579 .Case("t6", 14)
5580 .Case("t7", 15)
5581 .Case("t8", 24)
5582 .Case("t9", 25)
5583 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005584
Toma Tabacufda445c2014-09-15 15:33:01 +00005585 if (!(isABI_N32() || isABI_N64()))
5586 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005587
Daniel Sandersef638fe2014-10-03 15:37:37 +00005588 if (12 <= CC && CC <= 15) {
5589 // Name is one of t4-t7
5590 AsmToken RegTok = getLexer().peekTok();
5591 SMRange RegRange = RegTok.getLocRange();
5592
5593 StringRef FixedName = StringSwitch<StringRef>(Name)
5594 .Case("t4", "t0")
5595 .Case("t5", "t1")
5596 .Case("t6", "t2")
5597 .Case("t7", "t3")
5598 .Default("");
5599 assert(FixedName != "" && "Register name is not one of t4-t7.");
5600
5601 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5602 "Did you mean $" + FixedName + "?", RegRange);
5603 }
5604
Toma Tabacufda445c2014-09-15 15:33:01 +00005605 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5606 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5607 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5608 if (8 <= CC && CC <= 11)
5609 CC += 4;
5610
5611 if (CC == -1)
5612 CC = StringSwitch<unsigned>(Name)
5613 .Case("a4", 8)
5614 .Case("a5", 9)
5615 .Case("a6", 10)
5616 .Case("a7", 11)
5617 .Case("kt0", 26)
5618 .Case("kt1", 27)
5619 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005620
5621 return CC;
5622}
Jack Carterd0bd6422013-04-18 00:41:53 +00005623
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005624int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5625 int CC;
5626
5627 CC = StringSwitch<unsigned>(Name)
5628 .Case("hwr_cpunum", 0)
5629 .Case("hwr_synci_step", 1)
5630 .Case("hwr_cc", 2)
5631 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005632 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005633 .Default(-1);
5634
5635 return CC;
5636}
5637
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005638int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005639 if (Name[0] == 'f') {
5640 StringRef NumString = Name.substr(1);
5641 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005642 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005643 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005644 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005645 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005646 return IntVal;
5647 }
5648 return -1;
5649}
Jack Cartera63b16a2012-09-07 00:23:42 +00005650
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005651int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005652 if (Name.startswith("fcc")) {
5653 StringRef NumString = Name.substr(3);
5654 unsigned IntVal;
5655 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005656 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005657 if (IntVal > 7) // There are only 8 fcc registers.
5658 return -1;
5659 return IntVal;
5660 }
5661 return -1;
5662}
5663
5664int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005665 if (Name.startswith("ac")) {
5666 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005667 unsigned IntVal;
5668 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005669 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005670 if (IntVal > 3) // There are only 3 acc registers.
5671 return -1;
5672 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005673 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005674 return -1;
5675}
Jack Carterd0bd6422013-04-18 00:41:53 +00005676
Jack Carter5dc8ac92013-09-25 23:50:44 +00005677int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5678 unsigned IntVal;
5679
5680 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5681 return -1;
5682
5683 if (IntVal > 31)
5684 return -1;
5685
5686 return IntVal;
5687}
5688
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005689int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5690 int CC;
5691
5692 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005693 .Case("msair", 0)
5694 .Case("msacsr", 1)
5695 .Case("msaaccess", 2)
5696 .Case("msasave", 3)
5697 .Case("msamodify", 4)
5698 .Case("msarequest", 5)
5699 .Case("msamap", 6)
5700 .Case("msaunmap", 7)
5701 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005702
5703 return CC;
5704}
5705
Simon Dardis3aa8a902017-02-06 12:43:46 +00005706bool MipsAsmParser::canUseATReg() {
5707 return AssemblerOptions.back()->getATRegIndex() != 0;
5708}
5709
Toma Tabacu89a712b2015-04-15 10:48:56 +00005710unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005711 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005712 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005713 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005714 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005715 return 0;
5716 }
5717 unsigned AT = getReg(
5718 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005719 return AT;
5720}
Jack Carter0b744b32012-10-04 02:29:46 +00005721
Jack Carterd0bd6422013-04-18 00:41:53 +00005722unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005723 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005724}
5725
Toma Tabacu13964452014-09-04 13:23:44 +00005726bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005727 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005728 LLVM_DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005729
Jack Carter30a59822012-10-04 04:03:53 +00005730 // Check if the current operand has a custom associated parser, if so, try to
5731 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005732 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5733 if (ResTy == MatchOperand_Success)
5734 return false;
5735 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5736 // there was a match, but an error occurred, in which case, just return that
5737 // the operand parsing failed.
5738 if (ResTy == MatchOperand_ParseFail)
5739 return true;
5740
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005741 LLVM_DEBUG(dbgs() << ".. Generic Parser\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005742
Jack Carterb4dbc172012-09-05 23:34:03 +00005743 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005744 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005745 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005746 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005747
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005748 // Almost all registers have been parsed by custom parsers. There is only
5749 // one exception to this. $zero (and it's alias $0) will reach this point
5750 // for div, divu, and similar instructions because it is not an operand
5751 // to the instruction definition but an explicit register. Special case
5752 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005753 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005754 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005755
Jack Carterd0bd6422013-04-18 00:41:53 +00005756 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005757 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005758 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005759 return true;
5760
Jack Carter873c7242013-01-12 01:03:14 +00005761 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005762 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005763 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005764 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005765 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005766
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005767 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005768 return false;
5769 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005770 default: {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005771 LLVM_DEBUG(dbgs() << ".. generic integer expression\n");
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005772
5773 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005774 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005775 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005776 return true;
5777
Jack Carter873c7242013-01-12 01:03:14 +00005778 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5779
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005780 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005781 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005782 }
Jack Carter0b744b32012-10-04 02:29:46 +00005783 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005784 return true;
5785}
5786
Jack Carterb5cf5902013-04-17 00:18:04 +00005787bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005788 switch (Expr->getKind()) {
5789 case MCExpr::Constant:
5790 return true;
5791 case MCExpr::SymbolRef:
5792 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
Simon Dardisc6be2252017-08-09 10:47:52 +00005793 case MCExpr::Binary: {
Simon Dardis02c9a3d2017-08-18 13:27:02 +00005794 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
Simon Dardisc6be2252017-08-09 10:47:52 +00005795 if (!isEvaluated(BE->getLHS()))
5796 return false;
5797 return isEvaluated(BE->getRHS());
5798 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005799 case MCExpr::Unary:
5800 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005801 case MCExpr::Target:
5802 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005803 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005804 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005805}
Jack Carterd0bd6422013-04-18 00:41:53 +00005806
Jack Carterb4dbc172012-09-05 23:34:03 +00005807bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5808 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005809 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005810 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005811 if (ResTy == MatchOperand_Success) {
5812 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005813 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005814 StartLoc = Operand.getStartLoc();
5815 EndLoc = Operand.getEndLoc();
5816
5817 // AFAIK, we only support numeric registers and named GPR's in CFI
5818 // directives.
5819 // Don't worry about eating tokens before failing. Using an unrecognised
5820 // register is a parse error.
5821 if (Operand.isGPRAsmReg()) {
5822 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005823 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005824 }
5825
5826 return (RegNo == (unsigned)-1);
5827 }
5828
5829 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005830 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005831}
5832
Jack Carterb5cf5902013-04-17 00:18:04 +00005833bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005834 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005835
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005836 if (isParenExpr)
5837 return getParser().parseParenExprOfDepth(0, Res, S);
5838 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005839}
5840
Alex Bradbury58eba092016-11-01 16:32:05 +00005841OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005842MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005843 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005844 LLVM_DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005845 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005846 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005847 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005848 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005849 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005850 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005851
Jack Carterb5cf5902013-04-17 00:18:04 +00005852 if (getLexer().getKind() == AsmToken::LParen) {
5853 Parser.Lex();
5854 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005855 }
5856
Jack Carterb5cf5902013-04-17 00:18:04 +00005857 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005858 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005859 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005860
Jack Carterd0bd6422013-04-18 00:41:53 +00005861 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005862 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005863 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005864 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005865 SMLoc E =
5866 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005867 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005868 return MatchOperand_Success;
5869 }
5870 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005871 SMLoc E =
5872 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005873
Jack Carterd0bd6422013-04-18 00:41:53 +00005874 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005875 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005876 auto Base = MipsOperand::createGPRReg(
5877 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005878 Operands.push_back(
5879 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005880 return MatchOperand_Success;
5881 }
Simon Dardis858915f2016-10-18 15:17:17 +00005882 MCBinaryExpr::Opcode Opcode;
5883 // GAS and LLVM treat comparison operators different. GAS will generate -1
5884 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5885 // highly unlikely to be found in a memory offset expression, we don't
5886 // handle them.
5887 switch (Tok.getKind()) {
5888 case AsmToken::Plus:
5889 Opcode = MCBinaryExpr::Add;
5890 Parser.Lex();
5891 break;
5892 case AsmToken::Minus:
5893 Opcode = MCBinaryExpr::Sub;
5894 Parser.Lex();
5895 break;
5896 case AsmToken::Star:
5897 Opcode = MCBinaryExpr::Mul;
5898 Parser.Lex();
5899 break;
5900 case AsmToken::Pipe:
5901 Opcode = MCBinaryExpr::Or;
5902 Parser.Lex();
5903 break;
5904 case AsmToken::Amp:
5905 Opcode = MCBinaryExpr::And;
5906 Parser.Lex();
5907 break;
5908 case AsmToken::LessLess:
5909 Opcode = MCBinaryExpr::Shl;
5910 Parser.Lex();
5911 break;
5912 case AsmToken::GreaterGreater:
5913 Opcode = MCBinaryExpr::LShr;
5914 Parser.Lex();
5915 break;
5916 case AsmToken::Caret:
5917 Opcode = MCBinaryExpr::Xor;
5918 Parser.Lex();
5919 break;
5920 case AsmToken::Slash:
5921 Opcode = MCBinaryExpr::Div;
5922 Parser.Lex();
5923 break;
5924 case AsmToken::Percent:
5925 Opcode = MCBinaryExpr::Mod;
5926 Parser.Lex();
5927 break;
5928 default:
5929 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5930 return MatchOperand_ParseFail;
5931 }
5932 const MCExpr * NextExpr;
5933 if (getParser().parseExpression(NextExpr))
5934 return MatchOperand_ParseFail;
5935 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005936 }
5937
Jack Carterd0bd6422013-04-18 00:41:53 +00005938 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005939 }
5940
Toma Tabacu13964452014-09-04 13:23:44 +00005941 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005942 if (Res != MatchOperand_Success)
5943 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005944
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005945 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005946 Error(Parser.getTok().getLoc(), "')' expected");
5947 return MatchOperand_ParseFail;
5948 }
5949
Jack Carter873c7242013-01-12 01:03:14 +00005950 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5951
Jack Carterd0bd6422013-04-18 00:41:53 +00005952 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005953
Craig Topper062a2ba2014-04-25 05:30:21 +00005954 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005955 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005956
Jack Carterd0bd6422013-04-18 00:41:53 +00005957 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005958 std::unique_ptr<MipsOperand> op(
5959 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005960 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005961 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005962 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005963 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005964 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5965 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005966 if (IdVal->evaluateAsAbsolute(Imm))
5967 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005968 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005969 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005970 getContext());
5971 }
5972
David Blaikie960ea3f2014-06-08 16:18:35 +00005973 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005974 return MatchOperand_Success;
5975}
5976
David Blaikie960ea3f2014-06-08 16:18:35 +00005977bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005978 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005979 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00005980 if (!Sym)
5981 return false;
5982
5983 SMLoc S = Parser.getTok().getLoc();
5984 if (Sym->isVariable()) {
5985 const MCExpr *Expr = Sym->getVariableValue();
Jack Carterd76b2372013-03-21 21:44:16 +00005986 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005987 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005988 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005989 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005990 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005991 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005992 if (ResTy == MatchOperand_Success) {
5993 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005994 return true;
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00005995 }
5996 if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005997 llvm_unreachable("Should never ParseFail");
Jack Carterd76b2372013-03-21 21:44:16 +00005998 }
Jack Carterd76b2372013-03-21 21:44:16 +00005999 }
Simon Atanasyan69301c92018-05-29 15:58:06 +00006000 } else if (Sym->isUnset()) {
6001 // If symbol is unset, it might be created in the `parseSetAssignment`
6002 // routine as an alias for a numeric register name.
6003 // Lookup in the aliases list.
6004 auto Entry = RegisterSets.find(Sym->getName());
6005 if (Entry != RegisterSets.end()) {
6006 OperandMatchResultTy ResTy =
6007 matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S);
6008 if (ResTy == MatchOperand_Success) {
6009 Parser.Lex();
6010 return true;
6011 }
6012 }
Jack Carterd76b2372013-03-21 21:44:16 +00006013 }
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00006014
Jack Carterd76b2372013-03-21 21:44:16 +00006015 return false;
6016}
Jack Carterd0bd6422013-04-18 00:41:53 +00006017
Alex Bradbury58eba092016-11-01 16:32:05 +00006018OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006019MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00006020 StringRef Identifier,
6021 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006022 int Index = matchCPURegisterName(Identifier);
6023 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006024 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006025 Index, Identifier, getContext().getRegisterInfo(), S,
6026 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006027 return MatchOperand_Success;
6028 }
6029
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00006030 Index = matchHWRegsRegisterName(Identifier);
6031 if (Index != -1) {
6032 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006033 Index, Identifier, getContext().getRegisterInfo(), S,
6034 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00006035 return MatchOperand_Success;
6036 }
6037
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006038 Index = matchFPURegisterName(Identifier);
6039 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006040 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006041 Index, Identifier, getContext().getRegisterInfo(), S,
6042 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006043 return MatchOperand_Success;
6044 }
6045
6046 Index = matchFCCRegisterName(Identifier);
6047 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006048 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006049 Index, Identifier, getContext().getRegisterInfo(), S,
6050 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006051 return MatchOperand_Success;
6052 }
6053
6054 Index = matchACRegisterName(Identifier);
6055 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006056 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006057 Index, Identifier, getContext().getRegisterInfo(), S,
6058 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006059 return MatchOperand_Success;
6060 }
6061
6062 Index = matchMSA128RegisterName(Identifier);
6063 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006064 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006065 Index, Identifier, getContext().getRegisterInfo(), S,
6066 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006067 return MatchOperand_Success;
6068 }
6069
6070 Index = matchMSA128CtrlRegisterName(Identifier);
6071 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006072 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006073 Index, Identifier, getContext().getRegisterInfo(), S,
6074 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006075 return MatchOperand_Success;
6076 }
6077
6078 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00006079}
6080
Alex Bradbury58eba092016-11-01 16:32:05 +00006081OperandMatchResultTy
Simon Atanasyan69301c92018-05-29 15:58:06 +00006082MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands,
6083 const AsmToken &Token, SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006084 if (Token.is(AsmToken::Identifier)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006085 LLVM_DEBUG(dbgs() << ".. identifier\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006086 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00006087 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00006088 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00006089 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006090 } else if (Token.is(AsmToken::Integer)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006091 LLVM_DEBUG(dbgs() << ".. integer\n");
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006092 int64_t RegNum = Token.getIntVal();
6093 if (RegNum < 0 || RegNum > 31) {
6094 // Show the error, but treat invalid register
6095 // number as a normal one to continue parsing
6096 // and catch other possible errors.
6097 Error(getLexer().getLoc(), "invalid register number");
6098 }
Toma Tabacu13964452014-09-04 13:23:44 +00006099 Operands.push_back(MipsOperand::createNumericReg(
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006100 RegNum, Token.getString(), getContext().getRegisterInfo(), S,
Daniel Sandersc5537422016-07-27 13:49:44 +00006101 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006102 return MatchOperand_Success;
6103 }
6104
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00006105 LLVM_DEBUG(dbgs() << Token.getKind() << "\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006106
6107 return MatchOperand_NoMatch;
6108}
6109
Alex Bradbury58eba092016-11-01 16:32:05 +00006110OperandMatchResultTy
Simon Atanasyan69301c92018-05-29 15:58:06 +00006111MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
6112 auto Token = getLexer().peekTok(false);
6113 return matchAnyRegisterWithoutDollar(Operands, Token, S);
6114}
6115
6116OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006117MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006118 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006119 LLVM_DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006120
6121 auto Token = Parser.getTok();
6122
6123 SMLoc S = Token.getLoc();
6124
6125 if (Token.isNot(AsmToken::Dollar)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006126 LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006127 if (Token.is(AsmToken::Identifier)) {
6128 if (searchSymbolAlias(Operands))
6129 return MatchOperand_Success;
6130 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006131 LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006132 return MatchOperand_NoMatch;
6133 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006134 LLVM_DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006135
Toma Tabacu13964452014-09-04 13:23:44 +00006136 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00006137 if (ResTy == MatchOperand_Success) {
6138 Parser.Lex(); // $
6139 Parser.Lex(); // identifier
6140 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006141 return ResTy;
6142}
6143
Alex Bradbury58eba092016-11-01 16:32:05 +00006144OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006145MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006146 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006147 LLVM_DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006148
6149 SMLoc S = getLexer().getLoc();
6150
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006151 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006152 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006153 if (ResTy != MatchOperand_NoMatch)
6154 return ResTy;
6155
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006156 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00006157 const MCExpr *Expr = nullptr;
6158 if (Parser.parseExpression(Expr)) {
6159 // We have no way of knowing if a symbol was consumed so we must ParseFail
6160 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006161 }
Daniel Sandersffd84362014-04-01 10:41:48 +00006162 Operands.push_back(
6163 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006164 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00006165}
6166
Alex Bradbury58eba092016-11-01 16:32:05 +00006167OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00006168MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006169 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00006170 const MCExpr *IdVal;
Simon Dardisa17a7b62017-10-10 13:34:45 +00006171 // If the first token is '$' we may have register operand. We have to reject
6172 // cases where it is not a register. Complicating the matter is that
6173 // register names are not reserved across all ABIs.
6174 // Peek past the dollar to see if it's a register name for this ABI.
Vladimir Medic2b953d02013-10-01 09:48:56 +00006175 SMLoc S = Parser.getTok().getLoc();
Simon Dardisa17a7b62017-10-10 13:34:45 +00006176 if (Parser.getTok().is(AsmToken::Dollar)) {
6177 return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
6178 ? MatchOperand_ParseFail
6179 : MatchOperand_NoMatch;
6180 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00006181 if (getParser().parseExpression(IdVal))
6182 return MatchOperand_ParseFail;
6183 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Simon Dardisa17a7b62017-10-10 13:34:45 +00006184 if (!MCE)
6185 return MatchOperand_NoMatch;
Vladimir Medic2b953d02013-10-01 09:48:56 +00006186 int64_t Val = MCE->getValue();
6187 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
6188 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00006189 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00006190 return MatchOperand_Success;
6191}
6192
Alex Bradbury58eba092016-11-01 16:32:05 +00006193OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006194MipsAsmParser::parseRegisterList(OperandVector &Operands) {
6195 MCAsmParser &Parser = getParser();
6196 SmallVector<unsigned, 10> Regs;
6197 unsigned RegNo;
6198 unsigned PrevReg = Mips::NoRegister;
6199 bool RegRange = false;
6200 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6201
6202 if (Parser.getTok().isNot(AsmToken::Dollar))
6203 return MatchOperand_ParseFail;
6204
6205 SMLoc S = Parser.getTok().getLoc();
6206 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
6207 SMLoc E = getLexer().getLoc();
6208 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
6209 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
6210 if (RegRange) {
6211 // Remove last register operand because registers from register range
6212 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006213 if ((isGP64bit() && RegNo == Mips::RA_64) ||
6214 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006215 Regs.push_back(RegNo);
6216 } else {
6217 unsigned TmpReg = PrevReg + 1;
6218 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006219 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
6220 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
6221 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006222 Error(E, "invalid register operand");
6223 return MatchOperand_ParseFail;
6224 }
6225
6226 PrevReg = TmpReg;
6227 Regs.push_back(TmpReg++);
6228 }
6229 }
6230
6231 RegRange = false;
6232 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006233 if ((PrevReg == Mips::NoRegister) &&
6234 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
6235 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006236 Error(E, "$16 or $31 expected");
6237 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006238 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
6239 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
6240 !isGP64bit()) ||
6241 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
6242 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
6243 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006244 Error(E, "invalid register operand");
6245 return MatchOperand_ParseFail;
6246 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006247 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
6248 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
6249 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006250 Error(E, "consecutive register numbers expected");
6251 return MatchOperand_ParseFail;
6252 }
6253
6254 Regs.push_back(RegNo);
6255 }
6256
6257 if (Parser.getTok().is(AsmToken::Minus))
6258 RegRange = true;
6259
6260 if (!Parser.getTok().isNot(AsmToken::Minus) &&
6261 !Parser.getTok().isNot(AsmToken::Comma)) {
6262 Error(E, "',' or '-' expected");
6263 return MatchOperand_ParseFail;
6264 }
6265
6266 Lex(); // Consume comma or minus
6267 if (Parser.getTok().isNot(AsmToken::Dollar))
6268 break;
6269
6270 PrevReg = RegNo;
6271 }
6272
6273 SMLoc E = Parser.getTok().getLoc();
6274 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6275 parseMemOperand(Operands);
6276 return MatchOperand_Success;
6277}
6278
Alex Bradbury58eba092016-11-01 16:32:05 +00006279OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006280MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
6281 MCAsmParser &Parser = getParser();
6282
6283 SMLoc S = Parser.getTok().getLoc();
6284 if (parseAnyRegister(Operands) != MatchOperand_Success)
6285 return MatchOperand_ParseFail;
6286
6287 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00006288 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00006289
Benjamin Kramer2b68d152016-05-09 10:31:17 +00006290 Operands.pop_back();
6291 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006292 return MatchOperand_Success;
6293}
6294
Alex Bradbury58eba092016-11-01 16:32:05 +00006295OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00006296MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
6297 MCAsmParser &Parser = getParser();
6298 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6299 SmallVector<unsigned, 10> Regs;
6300
6301 if (Parser.getTok().isNot(AsmToken::Dollar))
6302 return MatchOperand_ParseFail;
6303
6304 SMLoc S = Parser.getTok().getLoc();
6305
6306 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6307 return MatchOperand_ParseFail;
6308
6309 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6310 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6311 Regs.push_back(RegNo);
6312
6313 SMLoc E = Parser.getTok().getLoc();
6314 if (Parser.getTok().isNot(AsmToken::Comma)) {
6315 Error(E, "',' expected");
6316 return MatchOperand_ParseFail;
6317 }
6318
6319 // Remove comma.
6320 Parser.Lex();
6321
6322 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6323 return MatchOperand_ParseFail;
6324
6325 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6326 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6327 Regs.push_back(RegNo);
6328
6329 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6330
6331 return MatchOperand_Success;
6332}
6333
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006334/// Sometimes (i.e. load/stores) the operand may be followed immediately by
6335/// either this.
6336/// ::= '(', register, ')'
6337/// handle it before we iterate so we don't get tripped up by the lack of
6338/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006339bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006340 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006341 if (getLexer().is(AsmToken::LParen)) {
6342 Operands.push_back(
6343 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
6344 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006345 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006346 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006347 return Error(Loc, "unexpected token in argument list");
6348 }
6349 if (Parser.getTok().isNot(AsmToken::RParen)) {
6350 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006351 return Error(Loc, "unexpected token, expected ')'");
6352 }
6353 Operands.push_back(
6354 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
6355 Parser.Lex();
6356 }
6357 return false;
6358}
6359
6360/// Sometimes (i.e. in MSA) the operand may be followed immediately by
6361/// either one of these.
6362/// ::= '[', register, ']'
6363/// ::= '[', integer, ']'
6364/// handle it before we iterate so we don't get tripped up by the lack of
6365/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006366bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00006367 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006368 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006369 if (getLexer().is(AsmToken::LBrac)) {
6370 Operands.push_back(
6371 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
6372 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006373 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006374 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006375 return Error(Loc, "unexpected token in argument list");
6376 }
6377 if (Parser.getTok().isNot(AsmToken::RBrac)) {
6378 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006379 return Error(Loc, "unexpected token, expected ']'");
6380 }
6381 Operands.push_back(
6382 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
6383 Parser.Lex();
6384 }
6385 return false;
6386}
6387
David Blaikie960ea3f2014-06-08 16:18:35 +00006388bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6389 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006390 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006391 LLVM_DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006392
6393 // We have reached first instruction, module directive are now forbidden.
6394 getTargetStreamer().forbidModuleDirective();
6395
Vladimir Medic74593e62013-07-17 15:00:42 +00006396 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006397 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006398 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00006399 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006400 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006401 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006402
6403 // Read the remaining operands.
6404 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6405 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006406 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006407 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006408 return Error(Loc, "unexpected token in argument list");
6409 }
Toma Tabacu13964452014-09-04 13:23:44 +00006410 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006411 return true;
6412 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006413
Jack Carterd0bd6422013-04-18 00:41:53 +00006414 while (getLexer().is(AsmToken::Comma)) {
6415 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006416 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006417 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006418 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006419 return Error(Loc, "unexpected token in argument list");
6420 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006421 // Parse bracket and parenthesis suffixes before we iterate
6422 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006423 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006424 return true;
6425 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006426 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006427 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006428 }
6429 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006430 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6431 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006432 return Error(Loc, "unexpected token in argument list");
6433 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006434 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006435 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006436}
6437
Nirav Dave996fc132016-05-05 14:15:46 +00006438// FIXME: Given that these have the same name, these should both be
6439// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006440bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006441 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006442 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006443}
6444
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006445bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006446 return Error(Loc, ErrorMsg);
6447}
6448
Jack Carter0b744b32012-10-04 02:29:46 +00006449bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006450 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006451 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006452
6453 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006454 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006455
6456 Parser.Lex(); // Eat "noat".
6457
Jack Carterd0bd6422013-04-18 00:41:53 +00006458 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006459 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006460 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006461 return false;
6462 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006463
6464 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006465 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006466 return false;
6467}
Jack Carterd0bd6422013-04-18 00:41:53 +00006468
Jack Carter0b744b32012-10-04 02:29:46 +00006469bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006470 // Line can be: ".set at", which sets $at to $1
6471 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006472 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006473 Parser.Lex(); // Eat "at".
6474
Jack Carter0b744b32012-10-04 02:29:46 +00006475 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006476 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006477 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006478
6479 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006480 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006481 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006482 }
6483
6484 if (getLexer().isNot(AsmToken::Equal)) {
6485 reportParseError("unexpected token, expected equals sign");
6486 return false;
6487 }
6488 Parser.Lex(); // Eat "=".
6489
6490 if (getLexer().isNot(AsmToken::Dollar)) {
6491 if (getLexer().is(AsmToken::EndOfStatement)) {
6492 reportParseError("no register specified");
6493 return false;
6494 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006495 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006496 return false;
6497 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006498 }
6499 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006500
Toma Tabacu16a74492015-02-13 10:30:57 +00006501 // Find out what "reg" is.
6502 unsigned AtRegNo;
6503 const AsmToken &Reg = Parser.getTok();
6504 if (Reg.is(AsmToken::Identifier)) {
6505 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6506 } else if (Reg.is(AsmToken::Integer)) {
6507 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006508 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006509 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006510 return false;
6511 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006512
6513 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006514 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006515 reportParseError("invalid register");
6516 return false;
6517 }
6518 Parser.Lex(); // Eat "reg".
6519
6520 // If this is not the end of the statement, report an error.
6521 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6522 reportParseError("unexpected token, expected end of statement");
6523 return false;
6524 }
6525
6526 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6527
6528 Parser.Lex(); // Consume the EndOfStatement.
6529 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006530}
6531
6532bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006533 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006534 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006535 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006536 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006537 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006538 return false;
6539 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006540 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006541 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006542 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006543 return false;
6544}
6545
6546bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006547 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006548 Parser.Lex();
6549 // If this is not the end of the statement, report an error.
6550 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006551 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006552 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006553 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006554 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006555 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006556 Parser.Lex(); // Consume the EndOfStatement.
6557 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006558}
6559
6560bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006561 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006562 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006563 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006564 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006565 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006566 return false;
6567 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006568 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006569 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006570 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006571 return false;
6572}
6573
6574bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006575 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006576 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006577 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006578 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006579 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006580 return false;
6581 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006582 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006583 reportParseError("`noreorder' must be set before `nomacro'");
6584 return false;
6585 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006586 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006587 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006588 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006589 return false;
6590}
Jack Carterd76b2372013-03-21 21:44:16 +00006591
Daniel Sanders44934432014-08-07 12:03:36 +00006592bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006593 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006594 Parser.Lex();
6595
6596 // If this is not the end of the statement, report an error.
6597 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006598 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006599
6600 setFeatureBits(Mips::FeatureMSA, "msa");
6601 getTargetStreamer().emitDirectiveSetMsa();
6602 return false;
6603}
6604
6605bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006606 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006607 Parser.Lex();
6608
6609 // If this is not the end of the statement, report an error.
6610 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006611 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006612
6613 clearFeatureBits(Mips::FeatureMSA, "msa");
6614 getTargetStreamer().emitDirectiveSetNoMsa();
6615 return false;
6616}
6617
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006618bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006619 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006620 Parser.Lex(); // Eat "nodsp".
6621
6622 // If this is not the end of the statement, report an error.
6623 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6624 reportParseError("unexpected token, expected end of statement");
6625 return false;
6626 }
6627
6628 clearFeatureBits(Mips::FeatureDSP, "dsp");
6629 getTargetStreamer().emitDirectiveSetNoDsp();
6630 return false;
6631}
6632
Toma Tabacucc2502d2014-11-04 17:18:07 +00006633bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006634 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006635 Parser.Lex(); // Eat "mips16".
6636
Jack Carter39536722014-01-22 23:08:42 +00006637 // If this is not the end of the statement, report an error.
6638 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006639 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006640 return false;
6641 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006642
6643 setFeatureBits(Mips::FeatureMips16, "mips16");
6644 getTargetStreamer().emitDirectiveSetMips16();
6645 Parser.Lex(); // Consume the EndOfStatement.
6646 return false;
6647}
6648
6649bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006650 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006651 Parser.Lex(); // Eat "nomips16".
6652
6653 // If this is not the end of the statement, report an error.
6654 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6655 reportParseError("unexpected token, expected end of statement");
6656 return false;
6657 }
6658
6659 clearFeatureBits(Mips::FeatureMips16, "mips16");
6660 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006661 Parser.Lex(); // Consume the EndOfStatement.
6662 return false;
6663}
6664
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006665bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006666 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006667 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006668 // Line can be: .set fp=32
6669 // .set fp=xx
6670 // .set fp=64
6671 Parser.Lex(); // Eat fp token
6672 AsmToken Tok = Parser.getTok();
6673 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006674 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006675 return false;
6676 }
6677 Parser.Lex(); // Eat '=' token.
6678 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006679
6680 if (!parseFpABIValue(FpAbiVal, ".set"))
6681 return false;
6682
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006683 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006684 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006685 return false;
6686 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006687 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006688 Parser.Lex(); // Consume the EndOfStatement.
6689 return false;
6690}
6691
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006692bool MipsAsmParser::parseSetOddSPRegDirective() {
6693 MCAsmParser &Parser = getParser();
6694
6695 Parser.Lex(); // Eat "oddspreg".
6696 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6697 reportParseError("unexpected token, expected end of statement");
6698 return false;
6699 }
6700
6701 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6702 getTargetStreamer().emitDirectiveSetOddSPReg();
6703 return false;
6704}
6705
6706bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6707 MCAsmParser &Parser = getParser();
6708
6709 Parser.Lex(); // Eat "nooddspreg".
6710 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6711 reportParseError("unexpected token, expected end of statement");
6712 return false;
6713 }
6714
6715 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6716 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6717 return false;
6718}
6719
Simon Dardis805f1e02017-07-11 21:28:36 +00006720bool MipsAsmParser::parseSetMtDirective() {
6721 MCAsmParser &Parser = getParser();
6722 Parser.Lex(); // Eat "mt".
6723
6724 // If this is not the end of the statement, report an error.
6725 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6726 reportParseError("unexpected token, expected end of statement");
6727 return false;
6728 }
6729
6730 setFeatureBits(Mips::FeatureMT, "mt");
6731 getTargetStreamer().emitDirectiveSetMt();
6732 Parser.Lex(); // Consume the EndOfStatement.
6733 return false;
6734}
6735
6736bool MipsAsmParser::parseSetNoMtDirective() {
6737 MCAsmParser &Parser = getParser();
6738 Parser.Lex(); // Eat "nomt".
6739
6740 // If this is not the end of the statement, report an error.
6741 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6742 reportParseError("unexpected token, expected end of statement");
6743 return false;
6744 }
6745
6746 clearFeatureBits(Mips::FeatureMT, "mt");
6747
6748 getTargetStreamer().emitDirectiveSetNoMt();
6749 Parser.Lex(); // Consume the EndOfStatement.
6750 return false;
6751}
6752
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006753bool MipsAsmParser::parseSetNoCRCDirective() {
6754 MCAsmParser &Parser = getParser();
6755 Parser.Lex(); // Eat "nocrc".
6756
6757 // If this is not the end of the statement, report an error.
6758 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6759 reportParseError("unexpected token, expected end of statement");
6760 return false;
6761 }
6762
6763 clearFeatureBits(Mips::FeatureCRC, "crc");
6764
6765 getTargetStreamer().emitDirectiveSetNoCRC();
6766 Parser.Lex(); // Consume the EndOfStatement.
6767 return false;
6768}
6769
Petar Jovanovicd4349f32018-04-27 09:12:08 +00006770bool MipsAsmParser::parseSetNoVirtDirective() {
6771 MCAsmParser &Parser = getParser();
6772 Parser.Lex(); // Eat "novirt".
6773
6774 // If this is not the end of the statement, report an error.
6775 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6776 reportParseError("unexpected token, expected end of statement");
6777 return false;
6778 }
6779
6780 clearFeatureBits(Mips::FeatureVirt, "virt");
6781
6782 getTargetStreamer().emitDirectiveSetNoVirt();
6783 Parser.Lex(); // Consume the EndOfStatement.
6784 return false;
6785}
6786
Petar Jovanovicdaf51692018-05-17 16:30:32 +00006787bool MipsAsmParser::parseSetNoGINVDirective() {
6788 MCAsmParser &Parser = getParser();
6789 Parser.Lex(); // Eat "noginv".
6790
6791 // If this is not the end of the statement, report an error.
6792 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6793 reportParseError("unexpected token, expected end of statement");
6794 return false;
6795 }
6796
6797 clearFeatureBits(Mips::FeatureGINV, "ginv");
6798
6799 getTargetStreamer().emitDirectiveSetNoGINV();
6800 Parser.Lex(); // Consume the EndOfStatement.
6801 return false;
6802}
6803
Toma Tabacu9db22db2014-09-09 10:15:38 +00006804bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006805 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006806 SMLoc Loc = getLexer().getLoc();
6807
6808 Parser.Lex();
6809 if (getLexer().isNot(AsmToken::EndOfStatement))
6810 return reportParseError("unexpected token, expected end of statement");
6811
6812 // Always keep an element on the options "stack" to prevent the user
6813 // from changing the initial options. This is how we remember them.
6814 if (AssemblerOptions.size() == 2)
6815 return reportParseError(Loc, ".set pop with no .set push");
6816
Akira Hatanakab11ef082015-11-14 06:35:56 +00006817 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006818 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006819 setAvailableFeatures(
6820 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6821 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006822
6823 getTargetStreamer().emitDirectiveSetPop();
6824 return false;
6825}
6826
6827bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006828 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006829 Parser.Lex();
6830 if (getLexer().isNot(AsmToken::EndOfStatement))
6831 return reportParseError("unexpected token, expected end of statement");
6832
6833 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006834 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006835 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006836
6837 getTargetStreamer().emitDirectiveSetPush();
6838 return false;
6839}
6840
Toma Tabacu29696502015-06-02 09:48:04 +00006841bool MipsAsmParser::parseSetSoftFloatDirective() {
6842 MCAsmParser &Parser = getParser();
6843 Parser.Lex();
6844 if (getLexer().isNot(AsmToken::EndOfStatement))
6845 return reportParseError("unexpected token, expected end of statement");
6846
6847 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6848 getTargetStreamer().emitDirectiveSetSoftFloat();
6849 return false;
6850}
6851
6852bool MipsAsmParser::parseSetHardFloatDirective() {
6853 MCAsmParser &Parser = getParser();
6854 Parser.Lex();
6855 if (getLexer().isNot(AsmToken::EndOfStatement))
6856 return reportParseError("unexpected token, expected end of statement");
6857
6858 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6859 getTargetStreamer().emitDirectiveSetHardFloat();
6860 return false;
6861}
6862
Jack Carterd76b2372013-03-21 21:44:16 +00006863bool MipsAsmParser::parseSetAssignment() {
6864 StringRef Name;
6865 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006866 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006867
6868 if (Parser.parseIdentifier(Name))
Simon Atanasyan3535cb12018-05-29 09:51:22 +00006869 return reportParseError("expected identifier after .set");
Jack Carterd76b2372013-03-21 21:44:16 +00006870
6871 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006872 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006873 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006874
Simon Atanasyan69301c92018-05-29 15:58:06 +00006875 if (getLexer().is(AsmToken::Dollar) &&
6876 getLexer().peekTok().is(AsmToken::Integer)) {
6877 // Parse assignment of a numeric register:
6878 // .set r1,$1
6879 Parser.Lex(); // Eat $.
6880 RegisterSets[Name] = Parser.getTok();
6881 Parser.Lex(); // Eat identifier.
6882 getContext().getOrCreateSymbol(Name);
6883 } else if (!Parser.parseExpression(Value)) {
6884 // Parse assignment of an expression including
6885 // symbolic registers:
6886 // .set $tmp, $BB0-$BB1
6887 // .set r2, $f2
6888 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
6889 Sym->setVariableValue(Value);
6890 } else {
Jack Carter02593002013-05-28 22:21:05 +00006891 return reportParseError("expected valid expression after comma");
Simon Atanasyan69301c92018-05-29 15:58:06 +00006892 }
Jack Carterd76b2372013-03-21 21:44:16 +00006893
6894 return false;
6895}
Jack Carterd0bd6422013-04-18 00:41:53 +00006896
Toma Tabacu26647792014-09-09 12:52:14 +00006897bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006898 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006899 Parser.Lex();
6900 if (getLexer().isNot(AsmToken::EndOfStatement))
6901 return reportParseError("unexpected token, expected end of statement");
6902
6903 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006904 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006905 setAvailableFeatures(
6906 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6907 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006908 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6909
6910 getTargetStreamer().emitDirectiveSetMips0();
6911 return false;
6912}
6913
Toma Tabacu85618b32014-08-19 14:22:52 +00006914bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006915 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006916 Parser.Lex();
6917 if (getLexer().isNot(AsmToken::Equal))
6918 return reportParseError("unexpected token, expected equals sign");
6919
6920 Parser.Lex();
6921 StringRef Arch;
6922 if (Parser.parseIdentifier(Arch))
6923 return reportParseError("expected arch identifier");
6924
6925 StringRef ArchFeatureName =
6926 StringSwitch<StringRef>(Arch)
6927 .Case("mips1", "mips1")
6928 .Case("mips2", "mips2")
6929 .Case("mips3", "mips3")
6930 .Case("mips4", "mips4")
6931 .Case("mips5", "mips5")
6932 .Case("mips32", "mips32")
6933 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006934 .Case("mips32r3", "mips32r3")
6935 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006936 .Case("mips32r6", "mips32r6")
6937 .Case("mips64", "mips64")
6938 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006939 .Case("mips64r3", "mips64r3")
6940 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006941 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006942 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006943 .Case("r4000", "mips3") // This is an implementation of Mips3.
6944 .Default("");
6945
6946 if (ArchFeatureName.empty())
6947 return reportParseError("unsupported architecture");
6948
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00006949 if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
6950 return reportParseError("mips64r6 does not support microMIPS");
6951
Toma Tabacu85618b32014-08-19 14:22:52 +00006952 selectArch(ArchFeatureName);
6953 getTargetStreamer().emitDirectiveSetArch(Arch);
6954 return false;
6955}
6956
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006957bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006958 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006959 Parser.Lex();
6960 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006961 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006962
Matheus Almeida2852af82014-04-22 10:15:54 +00006963 switch (Feature) {
6964 default:
6965 llvm_unreachable("Unimplemented feature");
6966 case Mips::FeatureDSP:
6967 setFeatureBits(Mips::FeatureDSP, "dsp");
6968 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006969 break;
Petar Jovanovic65f10242017-10-05 17:40:32 +00006970 case Mips::FeatureDSPR2:
6971 setFeatureBits(Mips::FeatureDSPR2, "dspr2");
6972 getTargetStreamer().emitDirectiveSetDspr2();
6973 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006974 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006975 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006976 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006977 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006978 case Mips::FeatureMips1:
6979 selectArch("mips1");
6980 getTargetStreamer().emitDirectiveSetMips1();
6981 break;
6982 case Mips::FeatureMips2:
6983 selectArch("mips2");
6984 getTargetStreamer().emitDirectiveSetMips2();
6985 break;
6986 case Mips::FeatureMips3:
6987 selectArch("mips3");
6988 getTargetStreamer().emitDirectiveSetMips3();
6989 break;
6990 case Mips::FeatureMips4:
6991 selectArch("mips4");
6992 getTargetStreamer().emitDirectiveSetMips4();
6993 break;
6994 case Mips::FeatureMips5:
6995 selectArch("mips5");
6996 getTargetStreamer().emitDirectiveSetMips5();
6997 break;
6998 case Mips::FeatureMips32:
6999 selectArch("mips32");
7000 getTargetStreamer().emitDirectiveSetMips32();
7001 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00007002 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00007003 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00007004 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00007005 break;
Daniel Sanders17793142015-02-18 16:24:50 +00007006 case Mips::FeatureMips32r3:
7007 selectArch("mips32r3");
7008 getTargetStreamer().emitDirectiveSetMips32R3();
7009 break;
7010 case Mips::FeatureMips32r5:
7011 selectArch("mips32r5");
7012 getTargetStreamer().emitDirectiveSetMips32R5();
7013 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00007014 case Mips::FeatureMips32r6:
7015 selectArch("mips32r6");
7016 getTargetStreamer().emitDirectiveSetMips32R6();
7017 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00007018 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00007019 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00007020 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00007021 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00007022 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00007023 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00007024 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00007025 break;
Daniel Sanders17793142015-02-18 16:24:50 +00007026 case Mips::FeatureMips64r3:
7027 selectArch("mips64r3");
7028 getTargetStreamer().emitDirectiveSetMips64R3();
7029 break;
7030 case Mips::FeatureMips64r5:
7031 selectArch("mips64r5");
7032 getTargetStreamer().emitDirectiveSetMips64R5();
7033 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00007034 case Mips::FeatureMips64r6:
7035 selectArch("mips64r6");
7036 getTargetStreamer().emitDirectiveSetMips64R6();
7037 break;
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007038 case Mips::FeatureCRC:
7039 setFeatureBits(Mips::FeatureCRC, "crc");
7040 getTargetStreamer().emitDirectiveSetCRC();
7041 break;
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007042 case Mips::FeatureVirt:
7043 setFeatureBits(Mips::FeatureVirt, "virt");
7044 getTargetStreamer().emitDirectiveSetVirt();
7045 break;
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007046 case Mips::FeatureGINV:
7047 setFeatureBits(Mips::FeatureGINV, "ginv");
7048 getTargetStreamer().emitDirectiveSetGINV();
7049 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00007050 }
7051 return false;
7052}
7053
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007054bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007055 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007056 if (getLexer().isNot(AsmToken::Comma)) {
7057 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007058 return Error(Loc, ErrorStr);
7059 }
7060
Matheus Almeida2852af82014-04-22 10:15:54 +00007061 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007062 return true;
7063}
7064
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007065// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
7066// In this class, it is only used for .cprestore.
7067// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
7068// MipsTargetELFStreamer and MipsAsmParser.
7069bool MipsAsmParser::isPicAndNotNxxAbi() {
7070 return inPicMode() && !(isABI_N32() || isABI_N64());
7071}
7072
Toma Tabacuc4c202a2014-10-01 14:53:19 +00007073bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00007074 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00007075 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007076
Toma Tabacudde4c462014-11-06 10:02:45 +00007077 if (inMips16Mode()) {
7078 reportParseError(".cpload is not supported in Mips16 mode");
7079 return false;
7080 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007081
David Blaikie960ea3f2014-06-08 16:18:35 +00007082 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00007083 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007084 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7085 reportParseError("expected register containing function address");
7086 return false;
7087 }
7088
David Blaikie960ea3f2014-06-08 16:18:35 +00007089 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
7090 if (!RegOpnd.isGPRAsmReg()) {
7091 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007092 return false;
7093 }
7094
Toma Tabacudde4c462014-11-06 10:02:45 +00007095 // If this is not the end of the statement, report an error.
7096 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7097 reportParseError("unexpected token, expected end of statement");
7098 return false;
7099 }
7100
Toma Tabacuc4c202a2014-10-01 14:53:19 +00007101 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007102 return false;
7103}
7104
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007105bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
7106 MCAsmParser &Parser = getParser();
7107
7108 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
7109 // is used in non-PIC mode.
7110
7111 if (inMips16Mode()) {
7112 reportParseError(".cprestore is not supported in Mips16 mode");
7113 return false;
7114 }
7115
7116 // Get the stack offset value.
7117 const MCExpr *StackOffset;
7118 int64_t StackOffsetVal;
7119 if (Parser.parseExpression(StackOffset)) {
7120 reportParseError("expected stack offset value");
7121 return false;
7122 }
7123
7124 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
7125 reportParseError("stack offset is not an absolute expression");
7126 return false;
7127 }
7128
7129 if (StackOffsetVal < 0) {
7130 Warning(Loc, ".cprestore with negative stack offset has no effect");
7131 IsCpRestoreSet = false;
7132 } else {
7133 IsCpRestoreSet = true;
7134 CpRestoreOffset = StackOffsetVal;
7135 }
7136
7137 // 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
Daniel Sandersdf8510d2016-05-11 12:48:19 +00007143 if (!getTargetStreamer().emitDirectiveCpRestore(
7144 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00007145 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007146 Parser.Lex(); // Consume the EndOfStatement.
7147 return false;
7148}
7149
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007150bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007151 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007152 unsigned FuncReg;
7153 unsigned Save;
7154 bool SaveIsReg = true;
7155
Matheus Almeida7e815762014-06-18 13:08:59 +00007156 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007157 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007158 if (ResTy == MatchOperand_NoMatch) {
7159 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00007160 return false;
7161 }
7162
7163 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7164 if (!FuncRegOpnd.isGPRAsmReg()) {
7165 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007166 return false;
7167 }
7168
7169 FuncReg = FuncRegOpnd.getGPR32Reg();
7170 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007171
Toma Tabacu65f10572014-09-16 15:00:52 +00007172 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007173 return true;
7174
Toma Tabacu13964452014-09-04 13:23:44 +00007175 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007176 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00007177 const MCExpr *OffsetExpr;
7178 int64_t OffsetVal;
7179 SMLoc ExprLoc = getLexer().getLoc();
7180
7181 if (Parser.parseExpression(OffsetExpr) ||
7182 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
7183 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00007184 return false;
7185 }
Daniel Sanders5d796282015-09-21 09:26:55 +00007186
7187 Save = OffsetVal;
7188 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00007189 } else {
7190 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7191 if (!SaveOpnd.isGPRAsmReg()) {
7192 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007193 return false;
7194 }
7195 Save = SaveOpnd.getGPR32Reg();
7196 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007197
Toma Tabacu65f10572014-09-16 15:00:52 +00007198 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007199 return true;
7200
Toma Tabacu8874eac2015-02-18 13:46:53 +00007201 const MCExpr *Expr;
7202 if (Parser.parseExpression(Expr)) {
7203 reportParseError("expected expression");
7204 return false;
7205 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007206
Toma Tabacu8874eac2015-02-18 13:46:53 +00007207 if (Expr->getKind() != MCExpr::SymbolRef) {
7208 reportParseError("expected symbol");
7209 return false;
7210 }
7211 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
7212
Daniel Sandersf173dda2015-09-22 10:50:09 +00007213 CpSaveLocation = Save;
7214 CpSaveLocationIsRegister = SaveIsReg;
7215
Toma Tabacu8874eac2015-02-18 13:46:53 +00007216 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
7217 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007218 return false;
7219}
7220
Daniel Sandersf173dda2015-09-22 10:50:09 +00007221bool MipsAsmParser::parseDirectiveCPReturn() {
7222 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
7223 CpSaveLocationIsRegister);
7224 return false;
7225}
7226
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007227bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007228 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007229 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7230 const AsmToken &Tok = Parser.getTok();
7231
7232 if (Tok.getString() == "2008") {
7233 Parser.Lex();
7234 getTargetStreamer().emitDirectiveNaN2008();
7235 return false;
7236 } else if (Tok.getString() == "legacy") {
7237 Parser.Lex();
7238 getTargetStreamer().emitDirectiveNaNLegacy();
7239 return false;
7240 }
7241 }
7242 // If we don't recognize the option passed to the .nan
7243 // directive (e.g. no option or unknown option), emit an error.
7244 reportParseError("invalid option in .nan directive");
7245 return false;
7246}
7247
Jack Carter0b744b32012-10-04 02:29:46 +00007248bool MipsAsmParser::parseDirectiveSet() {
Simon Atanasyand408ec42018-05-29 09:51:28 +00007249 const AsmToken &Tok = getParser().getTok();
7250 StringRef IdVal = Tok.getString();
7251 SMLoc Loc = Tok.getLoc();
Jack Carter0b744b32012-10-04 02:29:46 +00007252
Simon Atanasyand408ec42018-05-29 09:51:28 +00007253 if (IdVal == "noat")
Jack Carter0b744b32012-10-04 02:29:46 +00007254 return parseSetNoAtDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007255 if (IdVal == "at")
Jack Carter0b744b32012-10-04 02:29:46 +00007256 return parseSetAtDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007257 if (IdVal == "arch")
Toma Tabacu85618b32014-08-19 14:22:52 +00007258 return parseSetArchDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007259 if (IdVal == "bopt") {
7260 Warning(Loc, "'bopt' feature is unsupported");
Simon Dardisac9c30c2017-02-01 18:50:24 +00007261 getParser().Lex();
7262 return false;
Simon Atanasyand408ec42018-05-29 09:51:28 +00007263 }
7264 if (IdVal == "nobopt") {
Simon Dardisac9c30c2017-02-01 18:50:24 +00007265 // We're already running in nobopt mode, so nothing to do.
7266 getParser().Lex();
7267 return false;
Simon Atanasyand408ec42018-05-29 09:51:28 +00007268 }
7269 if (IdVal == "fp")
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007270 return parseSetFpDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007271 if (IdVal == "oddspreg")
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007272 return parseSetOddSPRegDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007273 if (IdVal == "nooddspreg")
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007274 return parseSetNoOddSPRegDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007275 if (IdVal == "pop")
Toma Tabacu9db22db2014-09-09 10:15:38 +00007276 return parseSetPopDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007277 if (IdVal == "push")
Toma Tabacu9db22db2014-09-09 10:15:38 +00007278 return parseSetPushDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007279 if (IdVal == "reorder")
Jack Carter0b744b32012-10-04 02:29:46 +00007280 return parseSetReorderDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007281 if (IdVal == "noreorder")
Jack Carter0b744b32012-10-04 02:29:46 +00007282 return parseSetNoReorderDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007283 if (IdVal == "macro")
Jack Carter0b744b32012-10-04 02:29:46 +00007284 return parseSetMacroDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007285 if (IdVal == "nomacro")
Jack Carter0b744b32012-10-04 02:29:46 +00007286 return parseSetNoMacroDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007287 if (IdVal == "mips16")
Toma Tabacucc2502d2014-11-04 17:18:07 +00007288 return parseSetMips16Directive();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007289 if (IdVal == "nomips16")
Jack Carter39536722014-01-22 23:08:42 +00007290 return parseSetNoMips16Directive();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007291 if (IdVal == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00007292 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007293 getTargetStreamer().emitDirectiveSetNoMicroMips();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007294 getParser().eatToEndOfStatement();
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007295 return false;
Simon Atanasyand408ec42018-05-29 09:51:28 +00007296 }
7297 if (IdVal == "micromips") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007298 if (hasMips64r6()) {
Simon Atanasyand408ec42018-05-29 09:51:28 +00007299 Error(Loc, ".set micromips directive is not supported with MIPS64R6");
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007300 return false;
7301 }
Matheus Almeida2852af82014-04-22 10:15:54 +00007302 return parseSetFeature(Mips::FeatureMicroMips);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007303 }
7304 if (IdVal == "mips0")
Toma Tabacu26647792014-09-09 12:52:14 +00007305 return parseSetMips0Directive();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007306 if (IdVal == "mips1")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007307 return parseSetFeature(Mips::FeatureMips1);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007308 if (IdVal == "mips2")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007309 return parseSetFeature(Mips::FeatureMips2);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007310 if (IdVal == "mips3")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007311 return parseSetFeature(Mips::FeatureMips3);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007312 if (IdVal == "mips4")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007313 return parseSetFeature(Mips::FeatureMips4);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007314 if (IdVal == "mips5")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007315 return parseSetFeature(Mips::FeatureMips5);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007316 if (IdVal == "mips32")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007317 return parseSetFeature(Mips::FeatureMips32);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007318 if (IdVal == "mips32r2")
Matheus Almeida2852af82014-04-22 10:15:54 +00007319 return parseSetFeature(Mips::FeatureMips32r2);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007320 if (IdVal == "mips32r3")
Daniel Sanders17793142015-02-18 16:24:50 +00007321 return parseSetFeature(Mips::FeatureMips32r3);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007322 if (IdVal == "mips32r5")
Daniel Sanders17793142015-02-18 16:24:50 +00007323 return parseSetFeature(Mips::FeatureMips32r5);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007324 if (IdVal == "mips32r6")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007325 return parseSetFeature(Mips::FeatureMips32r6);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007326 if (IdVal == "mips64")
Matheus Almeida2852af82014-04-22 10:15:54 +00007327 return parseSetFeature(Mips::FeatureMips64);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007328 if (IdVal == "mips64r2")
Matheus Almeida2852af82014-04-22 10:15:54 +00007329 return parseSetFeature(Mips::FeatureMips64r2);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007330 if (IdVal == "mips64r3")
Daniel Sanders17793142015-02-18 16:24:50 +00007331 return parseSetFeature(Mips::FeatureMips64r3);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007332 if (IdVal == "mips64r5")
Daniel Sanders17793142015-02-18 16:24:50 +00007333 return parseSetFeature(Mips::FeatureMips64r5);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007334 if (IdVal == "mips64r6") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007335 if (inMicroMipsMode()) {
Simon Atanasyand408ec42018-05-29 09:51:28 +00007336 Error(Loc, "MIPS64R6 is not supported with microMIPS");
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007337 return false;
7338 }
Daniel Sandersf0df2212014-08-04 12:20:00 +00007339 return parseSetFeature(Mips::FeatureMips64r6);
Jack Carter0b744b32012-10-04 02:29:46 +00007340 }
Simon Atanasyand408ec42018-05-29 09:51:28 +00007341 if (IdVal == "dsp")
7342 return parseSetFeature(Mips::FeatureDSP);
7343 if (IdVal == "dspr2")
7344 return parseSetFeature(Mips::FeatureDSPR2);
7345 if (IdVal == "nodsp")
7346 return parseSetNoDspDirective();
7347 if (IdVal == "msa")
7348 return parseSetMsaDirective();
7349 if (IdVal == "nomsa")
7350 return parseSetNoMsaDirective();
7351 if (IdVal == "mt")
7352 return parseSetMtDirective();
7353 if (IdVal == "nomt")
7354 return parseSetNoMtDirective();
7355 if (IdVal == "softfloat")
7356 return parseSetSoftFloatDirective();
7357 if (IdVal == "hardfloat")
7358 return parseSetHardFloatDirective();
7359 if (IdVal == "crc")
7360 return parseSetFeature(Mips::FeatureCRC);
7361 if (IdVal == "nocrc")
7362 return parseSetNoCRCDirective();
7363 if (IdVal == "virt")
7364 return parseSetFeature(Mips::FeatureVirt);
7365 if (IdVal == "novirt")
7366 return parseSetNoVirtDirective();
7367 if (IdVal == "ginv")
7368 return parseSetFeature(Mips::FeatureGINV);
7369 if (IdVal == "noginv")
7370 return parseSetNoGINVDirective();
Jack Carter07c818d2013-01-25 01:31:34 +00007371
Simon Atanasyand408ec42018-05-29 09:51:28 +00007372 // It is just an identifier, look for an assignment.
7373 return parseSetAssignment();
Jack Carter0b744b32012-10-04 02:29:46 +00007374}
7375
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007376/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00007377/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007378bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007379 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007380 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00007381 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00007382 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00007383 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00007384 return true;
7385
7386 getParser().getStreamer().EmitValue(Value, Size);
7387
7388 if (getLexer().is(AsmToken::EndOfStatement))
7389 break;
7390
Jack Carter07c818d2013-01-25 01:31:34 +00007391 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00007392 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00007393 Parser.Lex();
7394 }
7395 }
7396
7397 Parser.Lex();
7398 return false;
7399}
7400
Vladimir Medic4c299852013-11-06 11:27:05 +00007401/// parseDirectiveGpWord
7402/// ::= .gpword local_sym
7403bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007404 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00007405 const MCExpr *Value;
7406 // EmitGPRel32Value requires an expression, so we are using base class
7407 // method to evaluate the expression.
7408 if (getParser().parseExpression(Value))
7409 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00007410 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00007411
Vladimir Medice10c1122013-11-13 13:18:04 +00007412 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00007413 return Error(getLexer().getLoc(),
7414 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00007415 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00007416 return false;
7417}
7418
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007419/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00007420/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007421bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007422 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007423 const MCExpr *Value;
7424 // EmitGPRel64Value requires an expression, so we are using base class
7425 // method to evaluate the expression.
7426 if (getParser().parseExpression(Value))
7427 return true;
7428 getParser().getStreamer().EmitGPRel64Value(Value);
7429
7430 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007431 return Error(getLexer().getLoc(),
7432 "unexpected token, expected end of statement");
7433 Parser.Lex(); // Eat EndOfStatement token.
7434 return false;
7435}
7436
7437/// parseDirectiveDtpRelWord
7438/// ::= .dtprelword tls_sym
7439bool MipsAsmParser::parseDirectiveDtpRelWord() {
7440 MCAsmParser &Parser = getParser();
7441 const MCExpr *Value;
7442 // EmitDTPRel32Value requires an expression, so we are using base class
7443 // method to evaluate the expression.
7444 if (getParser().parseExpression(Value))
7445 return true;
7446 getParser().getStreamer().EmitDTPRel32Value(Value);
7447
7448 if (getLexer().isNot(AsmToken::EndOfStatement))
7449 return Error(getLexer().getLoc(),
7450 "unexpected token, expected end of statement");
7451 Parser.Lex(); // Eat EndOfStatement token.
7452 return false;
7453}
7454
7455/// parseDirectiveDtpRelDWord
7456/// ::= .dtpreldword tls_sym
7457bool MipsAsmParser::parseDirectiveDtpRelDWord() {
7458 MCAsmParser &Parser = getParser();
7459 const MCExpr *Value;
7460 // EmitDTPRel64Value requires an expression, so we are using base class
7461 // method to evaluate the expression.
7462 if (getParser().parseExpression(Value))
7463 return true;
7464 getParser().getStreamer().EmitDTPRel64Value(Value);
7465
7466 if (getLexer().isNot(AsmToken::EndOfStatement))
7467 return Error(getLexer().getLoc(),
7468 "unexpected token, expected end of statement");
7469 Parser.Lex(); // Eat EndOfStatement token.
7470 return false;
7471}
7472
7473/// parseDirectiveTpRelWord
7474/// ::= .tprelword tls_sym
7475bool MipsAsmParser::parseDirectiveTpRelWord() {
7476 MCAsmParser &Parser = getParser();
7477 const MCExpr *Value;
7478 // EmitTPRel32Value requires an expression, so we are using base class
7479 // method to evaluate the expression.
7480 if (getParser().parseExpression(Value))
7481 return true;
7482 getParser().getStreamer().EmitTPRel32Value(Value);
7483
7484 if (getLexer().isNot(AsmToken::EndOfStatement))
7485 return Error(getLexer().getLoc(),
7486 "unexpected token, expected end of statement");
7487 Parser.Lex(); // Eat EndOfStatement token.
7488 return false;
7489}
7490
7491/// parseDirectiveTpRelDWord
7492/// ::= .tpreldword tls_sym
7493bool MipsAsmParser::parseDirectiveTpRelDWord() {
7494 MCAsmParser &Parser = getParser();
7495 const MCExpr *Value;
7496 // EmitTPRel64Value requires an expression, so we are using base class
7497 // method to evaluate the expression.
7498 if (getParser().parseExpression(Value))
7499 return true;
7500 getParser().getStreamer().EmitTPRel64Value(Value);
7501
7502 if (getLexer().isNot(AsmToken::EndOfStatement))
7503 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007504 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00007505 Parser.Lex(); // Eat EndOfStatement token.
7506 return false;
7507}
7508
Jack Carter0cd3c192014-01-06 23:27:31 +00007509bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007510 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00007511 // Get the option token.
7512 AsmToken Tok = Parser.getTok();
7513 // At the moment only identifiers are supported.
7514 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007515 return Error(Parser.getTok().getLoc(),
7516 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00007517 }
7518
7519 StringRef Option = Tok.getIdentifier();
7520
7521 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007522 // MipsAsmParser needs to know if the current PIC mode changes.
7523 IsPicEnabled = false;
7524
Jack Carter0cd3c192014-01-06 23:27:31 +00007525 getTargetStreamer().emitDirectiveOptionPic0();
7526 Parser.Lex();
7527 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007528 return Error(Parser.getTok().getLoc(),
7529 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007530 }
7531 return false;
7532 }
7533
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007534 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007535 // MipsAsmParser needs to know if the current PIC mode changes.
7536 IsPicEnabled = true;
7537
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007538 getTargetStreamer().emitDirectiveOptionPic2();
7539 Parser.Lex();
7540 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007541 return Error(Parser.getTok().getLoc(),
7542 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007543 }
7544 return false;
7545 }
7546
Jack Carter0cd3c192014-01-06 23:27:31 +00007547 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00007548 Warning(Parser.getTok().getLoc(),
7549 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007550 Parser.eatToEndOfStatement();
7551 return false;
7552}
7553
Toma Tabacu9ca50962015-04-16 09:53:47 +00007554/// parseInsnDirective
7555/// ::= .insn
7556bool MipsAsmParser::parseInsnDirective() {
7557 // If this is not the end of the statement, report an error.
7558 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7559 reportParseError("unexpected token, expected end of statement");
7560 return false;
7561 }
7562
7563 // The actual label marking happens in
7564 // MipsELFStreamer::createPendingLabelRelocs().
7565 getTargetStreamer().emitDirectiveInsn();
7566
7567 getParser().Lex(); // Eat EndOfStatement token.
7568 return false;
7569}
7570
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007571/// parseRSectionDirective
7572/// ::= .rdata
7573bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
7574 // If this is not the end of the statement, report an error.
7575 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7576 reportParseError("unexpected token, expected end of statement");
7577 return false;
7578 }
7579
7580 MCSection *ELFSection = getContext().getELFSection(
7581 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7582 getParser().getStreamer().SwitchSection(ELFSection);
7583
7584 getParser().Lex(); // Eat EndOfStatement token.
7585 return false;
7586}
7587
Simon Atanasyanbe186202016-02-11 06:45:54 +00007588/// parseSSectionDirective
7589/// ::= .sbss
7590/// ::= .sdata
7591bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7592 // If this is not the end of the statement, report an error.
7593 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7594 reportParseError("unexpected token, expected end of statement");
7595 return false;
7596 }
7597
7598 MCSection *ELFSection = getContext().getELFSection(
7599 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7600 getParser().getStreamer().SwitchSection(ELFSection);
7601
7602 getParser().Lex(); // Eat EndOfStatement token.
7603 return false;
7604}
7605
Daniel Sanders7e527422014-07-10 13:38:23 +00007606/// parseDirectiveModule
7607/// ::= .module oddspreg
7608/// ::= .module nooddspreg
7609/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007610/// ::= .module softfloat
7611/// ::= .module hardfloat
Simon Dardis805f1e02017-07-11 21:28:36 +00007612/// ::= .module mt
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007613/// ::= .module crc
7614/// ::= .module nocrc
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007615/// ::= .module virt
7616/// ::= .module novirt
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007617/// ::= .module ginv
7618/// ::= .module noginv
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007619bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007620 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007621 MCAsmLexer &Lexer = getLexer();
7622 SMLoc L = Lexer.getLoc();
7623
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007624 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007625 // TODO : get a better message.
7626 reportParseError(".module directive must appear before any code");
7627 return false;
7628 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007629
Toma Tabacuc405c822015-01-23 10:40:19 +00007630 StringRef Option;
7631 if (Parser.parseIdentifier(Option)) {
7632 reportParseError("expected .module option identifier");
7633 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007634 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007635
Toma Tabacuc405c822015-01-23 10:40:19 +00007636 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007637 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007638
Toma Tabacu3c499582015-06-25 10:56:57 +00007639 // Synchronize the abiflags information with the FeatureBits information we
7640 // changed above.
7641 getTargetStreamer().updateABIInfo(*this);
7642
7643 // If printing assembly, use the recently updated abiflags information.
7644 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7645 // emitted at the end).
7646 getTargetStreamer().emitDirectiveModuleOddSPReg();
7647
Toma Tabacuc405c822015-01-23 10:40:19 +00007648 // If this is not the end of the statement, report an error.
7649 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7650 reportParseError("unexpected token, expected end of statement");
7651 return false;
7652 }
7653
7654 return false; // parseDirectiveModule has finished successfully.
7655 } else if (Option == "nooddspreg") {
7656 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007657 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007658 }
7659
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007660 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007661
Toma Tabacu3c499582015-06-25 10:56:57 +00007662 // Synchronize the abiflags information with the FeatureBits information we
7663 // changed above.
7664 getTargetStreamer().updateABIInfo(*this);
7665
7666 // If printing assembly, use the recently updated abiflags information.
7667 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7668 // emitted at the end).
7669 getTargetStreamer().emitDirectiveModuleOddSPReg();
7670
Toma Tabacuc405c822015-01-23 10:40:19 +00007671 // If this is not the end of the statement, report an error.
7672 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7673 reportParseError("unexpected token, expected end of statement");
7674 return false;
7675 }
7676
7677 return false; // parseDirectiveModule has finished successfully.
7678 } else if (Option == "fp") {
7679 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007680 } else if (Option == "softfloat") {
7681 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7682
7683 // Synchronize the ABI Flags information with the FeatureBits information we
7684 // updated above.
7685 getTargetStreamer().updateABIInfo(*this);
7686
7687 // If printing assembly, use the recently updated ABI Flags information.
7688 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7689 // emitted later).
7690 getTargetStreamer().emitDirectiveModuleSoftFloat();
7691
7692 // If this is not the end of the statement, report an error.
7693 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7694 reportParseError("unexpected token, expected end of statement");
7695 return false;
7696 }
7697
7698 return false; // parseDirectiveModule has finished successfully.
7699 } else if (Option == "hardfloat") {
7700 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7701
7702 // Synchronize the ABI Flags information with the FeatureBits information we
7703 // updated above.
7704 getTargetStreamer().updateABIInfo(*this);
7705
7706 // If printing assembly, use the recently updated ABI Flags information.
7707 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7708 // emitted later).
7709 getTargetStreamer().emitDirectiveModuleHardFloat();
7710
7711 // If this is not the end of the statement, report an error.
7712 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7713 reportParseError("unexpected token, expected end of statement");
7714 return false;
7715 }
7716
7717 return false; // parseDirectiveModule has finished successfully.
Simon Dardis805f1e02017-07-11 21:28:36 +00007718 } else if (Option == "mt") {
7719 setModuleFeatureBits(Mips::FeatureMT, "mt");
7720
7721 // Synchronize the ABI Flags information with the FeatureBits information we
7722 // updated above.
7723 getTargetStreamer().updateABIInfo(*this);
7724
Simon Dardisd9611922017-07-11 21:36:58 +00007725 // If printing assembly, use the recently updated ABI Flags information.
Simon Dardis805f1e02017-07-11 21:28:36 +00007726 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7727 // emitted later).
7728 getTargetStreamer().emitDirectiveModuleMT();
7729
7730 // If this is not the end of the statement, report an error.
7731 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7732 reportParseError("unexpected token, expected end of statement");
7733 return false;
7734 }
7735
7736 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007737 } else if (Option == "crc") {
7738 setModuleFeatureBits(Mips::FeatureCRC, "crc");
7739
7740 // Synchronize the ABI Flags information with the FeatureBits information we
7741 // updated above.
7742 getTargetStreamer().updateABIInfo(*this);
7743
7744 // If printing assembly, use the recently updated ABI Flags information.
7745 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7746 // emitted later).
7747 getTargetStreamer().emitDirectiveModuleCRC();
7748
7749 // If this is not the end of the statement, report an error.
7750 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7751 reportParseError("unexpected token, expected end of statement");
7752 return false;
7753 }
7754
7755 return false; // parseDirectiveModule has finished successfully.
7756 } else if (Option == "nocrc") {
7757 clearModuleFeatureBits(Mips::FeatureCRC, "crc");
7758
7759 // Synchronize the ABI Flags information with the FeatureBits information we
7760 // updated above.
7761 getTargetStreamer().updateABIInfo(*this);
7762
7763 // If printing assembly, use the recently updated ABI Flags information.
7764 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7765 // emitted later).
7766 getTargetStreamer().emitDirectiveModuleNoCRC();
7767
7768 // If this is not the end of the statement, report an error.
7769 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7770 reportParseError("unexpected token, expected end of statement");
7771 return false;
7772 }
7773
7774 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007775 } else if (Option == "virt") {
7776 setModuleFeatureBits(Mips::FeatureVirt, "virt");
7777
7778 // Synchronize the ABI Flags information with the FeatureBits information we
7779 // updated above.
7780 getTargetStreamer().updateABIInfo(*this);
7781
7782 // If printing assembly, use the recently updated ABI Flags information.
7783 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7784 // emitted later).
7785 getTargetStreamer().emitDirectiveModuleVirt();
7786
7787 // If this is not the end of the statement, report an error.
7788 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7789 reportParseError("unexpected token, expected end of statement");
7790 return false;
7791 }
7792
7793 return false; // parseDirectiveModule has finished successfully.
7794 } else if (Option == "novirt") {
7795 clearModuleFeatureBits(Mips::FeatureVirt, "virt");
7796
7797 // Synchronize the ABI Flags information with the FeatureBits information we
7798 // updated above.
7799 getTargetStreamer().updateABIInfo(*this);
7800
7801 // If printing assembly, use the recently updated ABI Flags information.
7802 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7803 // emitted later).
7804 getTargetStreamer().emitDirectiveModuleNoVirt();
7805
7806 // If this is not the end of the statement, report an error.
7807 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7808 reportParseError("unexpected token, expected end of statement");
7809 return false;
7810 }
7811
7812 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007813 } else if (Option == "ginv") {
7814 setModuleFeatureBits(Mips::FeatureGINV, "ginv");
7815
7816 // Synchronize the ABI Flags information with the FeatureBits information we
7817 // updated above.
7818 getTargetStreamer().updateABIInfo(*this);
7819
7820 // If printing assembly, use the recently updated ABI Flags information.
7821 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7822 // emitted later).
7823 getTargetStreamer().emitDirectiveModuleGINV();
7824
7825 // If this is not the end of the statement, report an error.
7826 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7827 reportParseError("unexpected token, expected end of statement");
7828 return false;
7829 }
7830
7831 return false; // parseDirectiveModule has finished successfully.
7832 } else if (Option == "noginv") {
7833 clearModuleFeatureBits(Mips::FeatureGINV, "ginv");
7834
7835 // Synchronize the ABI Flags information with the FeatureBits information we
7836 // updated above.
7837 getTargetStreamer().updateABIInfo(*this);
7838
7839 // If printing assembly, use the recently updated ABI Flags information.
7840 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7841 // emitted later).
7842 getTargetStreamer().emitDirectiveModuleNoGINV();
7843
7844 // If this is not the end of the statement, report an error.
7845 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7846 reportParseError("unexpected token, expected end of statement");
7847 return false;
7848 }
7849
7850 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007851 } else {
7852 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7853 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007854}
7855
7856/// parseDirectiveModuleFP
7857/// ::= =32
7858/// ::= =xx
7859/// ::= =64
7860bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007861 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007862 MCAsmLexer &Lexer = getLexer();
7863
7864 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007865 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007866 return false;
7867 }
7868 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007869
Daniel Sanders7e527422014-07-10 13:38:23 +00007870 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007871 if (!parseFpABIValue(FpABI, ".module"))
7872 return false;
7873
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007874 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007875 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007876 return false;
7877 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007878
Toma Tabacua64e5402015-06-25 12:44:38 +00007879 // Synchronize the abiflags information with the FeatureBits information we
7880 // changed above.
7881 getTargetStreamer().updateABIInfo(*this);
7882
7883 // If printing assembly, use the recently updated abiflags information.
7884 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7885 // emitted at the end).
7886 getTargetStreamer().emitDirectiveModuleFP();
7887
Daniel Sanders7e527422014-07-10 13:38:23 +00007888 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007889 return false;
7890}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007891
Daniel Sanders7e527422014-07-10 13:38:23 +00007892bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007893 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007894 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007895 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007896 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007897
7898 if (Lexer.is(AsmToken::Identifier)) {
7899 StringRef Value = Parser.getTok().getString();
7900 Parser.Lex();
7901
7902 if (Value != "xx") {
7903 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7904 return false;
7905 }
7906
7907 if (!isABI_O32()) {
7908 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7909 return false;
7910 }
7911
Daniel Sanders7e527422014-07-10 13:38:23 +00007912 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007913 if (ModuleLevelOptions) {
7914 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7915 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7916 } else {
7917 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7918 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7919 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007920 return true;
7921 }
7922
7923 if (Lexer.is(AsmToken::Integer)) {
7924 unsigned Value = Parser.getTok().getIntVal();
7925 Parser.Lex();
7926
7927 if (Value != 32 && Value != 64) {
7928 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7929 return false;
7930 }
7931
7932 if (Value == 32) {
7933 if (!isABI_O32()) {
7934 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7935 return false;
7936 }
7937
Daniel Sanders7e527422014-07-10 13:38:23 +00007938 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007939 if (ModuleLevelOptions) {
7940 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7941 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7942 } else {
7943 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7944 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7945 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007946 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007947 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007948 if (ModuleLevelOptions) {
7949 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7950 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7951 } else {
7952 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7953 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7954 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007955 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007956
Daniel Sanders7e527422014-07-10 13:38:23 +00007957 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007958 }
7959
7960 return false;
7961}
7962
Jack Carter0b744b32012-10-04 02:29:46 +00007963bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007964 // This returns false if this function recognizes the directive
7965 // regardless of whether it is successfully handles or reports an
7966 // error. Otherwise it returns true to give the generic parser a
7967 // chance at recognizing it.
7968
Rafael Espindola961d4692014-11-11 05:18:41 +00007969 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007970 StringRef IDVal = DirectiveID.getString();
7971
Nirav Dave996fc132016-05-05 14:15:46 +00007972 if (IDVal == ".cpload") {
7973 parseDirectiveCpLoad(DirectiveID.getLoc());
7974 return false;
7975 }
7976 if (IDVal == ".cprestore") {
7977 parseDirectiveCpRestore(DirectiveID.getLoc());
7978 return false;
7979 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00007980 if (IDVal == ".dword") {
7981 parseDataDirective(8, DirectiveID.getLoc());
7982 return false;
7983 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007984 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007985 StringRef SymbolName;
7986
7987 if (Parser.parseIdentifier(SymbolName)) {
7988 reportParseError("expected identifier after .ent");
7989 return false;
7990 }
7991
7992 // There's an undocumented extension that allows an integer to
7993 // follow the name of the procedure which AFAICS is ignored by GAS.
7994 // Example: .ent foo,2
7995 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7996 if (getLexer().isNot(AsmToken::Comma)) {
7997 // Even though we accept this undocumented extension for compatibility
7998 // reasons, the additional integer argument does not actually change
7999 // the behaviour of the '.ent' directive, so we would like to discourage
8000 // its use. We do this by not referring to the extended version in
8001 // error messages which are not directly related to its use.
8002 reportParseError("unexpected token, expected end of statement");
8003 return false;
8004 }
8005 Parser.Lex(); // Eat the comma.
8006 const MCExpr *DummyNumber;
8007 int64_t DummyNumberVal;
8008 // If the user was explicitly trying to use the extended version,
8009 // we still give helpful extension-related error messages.
8010 if (Parser.parseExpression(DummyNumber)) {
8011 reportParseError("expected number after comma");
8012 return false;
8013 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00008014 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008015 reportParseError("expected an absolute expression after comma");
8016 return false;
8017 }
8018 }
8019
8020 // If this is not the end of the statement, report an error.
8021 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8022 reportParseError("unexpected token, expected end of statement");
8023 return false;
8024 }
8025
Jim Grosbach6f482002015-05-18 18:43:14 +00008026 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00008027
8028 getTargetStreamer().emitDirectiveEnt(*Sym);
8029 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00008030 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00008031 return false;
8032 }
8033
Jack Carter07c818d2013-01-25 01:31:34 +00008034 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008035 StringRef SymbolName;
8036
8037 if (Parser.parseIdentifier(SymbolName)) {
8038 reportParseError("expected identifier after .end");
8039 return false;
8040 }
8041
8042 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8043 reportParseError("unexpected token, expected end of statement");
8044 return false;
8045 }
8046
8047 if (CurrentFn == nullptr) {
8048 reportParseError(".end used without .ent");
8049 return false;
8050 }
8051
8052 if ((SymbolName != CurrentFn->getName())) {
8053 reportParseError(".end symbol does not match .ent symbol");
8054 return false;
8055 }
8056
8057 getTargetStreamer().emitDirectiveEnd(SymbolName);
8058 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00008059 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00008060 return false;
8061 }
8062
Jack Carter07c818d2013-01-25 01:31:34 +00008063 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008064 // .frame $stack_reg, frame_size_in_bytes, $return_reg
8065 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00008066 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00008067 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
8068 reportParseError("expected stack register");
8069 return false;
8070 }
8071
8072 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
8073 if (!StackRegOpnd.isGPRAsmReg()) {
8074 reportParseError(StackRegOpnd.getStartLoc(),
8075 "expected general purpose register");
8076 return false;
8077 }
8078 unsigned StackReg = StackRegOpnd.getGPR32Reg();
8079
8080 if (Parser.getTok().is(AsmToken::Comma))
8081 Parser.Lex();
8082 else {
8083 reportParseError("unexpected token, expected comma");
8084 return false;
8085 }
8086
8087 // Parse the frame size.
8088 const MCExpr *FrameSize;
8089 int64_t FrameSizeVal;
8090
8091 if (Parser.parseExpression(FrameSize)) {
8092 reportParseError("expected frame size value");
8093 return false;
8094 }
8095
Jim Grosbach13760bd2015-05-30 01:25:56 +00008096 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008097 reportParseError("frame size not an absolute expression");
8098 return false;
8099 }
8100
8101 if (Parser.getTok().is(AsmToken::Comma))
8102 Parser.Lex();
8103 else {
8104 reportParseError("unexpected token, expected comma");
8105 return false;
8106 }
8107
8108 // Parse the return register.
8109 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00008110 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00008111 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
8112 reportParseError("expected return register");
8113 return false;
8114 }
8115
8116 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
8117 if (!ReturnRegOpnd.isGPRAsmReg()) {
8118 reportParseError(ReturnRegOpnd.getStartLoc(),
8119 "expected general purpose register");
8120 return false;
8121 }
8122
8123 // If this is not the end of the statement, report an error.
8124 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8125 reportParseError("unexpected token, expected end of statement");
8126 return false;
8127 }
8128
8129 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
8130 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00008131 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00008132 return false;
8133 }
8134
Jack Carter07c818d2013-01-25 01:31:34 +00008135 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00008136 parseDirectiveSet();
8137 return false;
Jack Carterbe332172012-09-07 00:48:02 +00008138 }
8139
Daniel Sandersd97a6342014-08-13 10:07:34 +00008140 if (IDVal == ".mask" || IDVal == ".fmask") {
8141 // .mask bitmask, frame_offset
8142 // bitmask: One bit for each register used.
8143 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
8144 // first register is expected to be saved.
8145 // Examples:
8146 // .mask 0x80000000, -4
8147 // .fmask 0x80000000, -4
8148 //
Jack Carterbe332172012-09-07 00:48:02 +00008149
Daniel Sandersd97a6342014-08-13 10:07:34 +00008150 // Parse the bitmask
8151 const MCExpr *BitMask;
8152 int64_t BitMaskVal;
8153
8154 if (Parser.parseExpression(BitMask)) {
8155 reportParseError("expected bitmask value");
8156 return false;
8157 }
8158
Jim Grosbach13760bd2015-05-30 01:25:56 +00008159 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008160 reportParseError("bitmask not an absolute expression");
8161 return false;
8162 }
8163
8164 if (Parser.getTok().is(AsmToken::Comma))
8165 Parser.Lex();
8166 else {
8167 reportParseError("unexpected token, expected comma");
8168 return false;
8169 }
8170
8171 // Parse the frame_offset
8172 const MCExpr *FrameOffset;
8173 int64_t FrameOffsetVal;
8174
8175 if (Parser.parseExpression(FrameOffset)) {
8176 reportParseError("expected frame offset value");
8177 return false;
8178 }
8179
Jim Grosbach13760bd2015-05-30 01:25:56 +00008180 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008181 reportParseError("frame offset not an absolute expression");
8182 return false;
8183 }
8184
8185 // If this is not the end of the statement, report an error.
8186 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8187 reportParseError("unexpected token, expected end of statement");
8188 return false;
8189 }
8190
8191 if (IDVal == ".mask")
8192 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
8193 else
8194 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00008195 return false;
8196 }
8197
Matheus Almeida0051f2d2014-04-16 15:48:55 +00008198 if (IDVal == ".nan")
8199 return parseDirectiveNaN();
8200
Jack Carter07c818d2013-01-25 01:31:34 +00008201 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00008202 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00008203 return false;
8204 }
8205
Rafael Espindolab59fb732014-03-28 18:50:26 +00008206 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00008207 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00008208 return false;
8209 }
8210
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00008211 if (IDVal == ".dtprelword") {
8212 parseDirectiveDtpRelWord();
8213 return false;
8214 }
8215
8216 if (IDVal == ".dtpreldword") {
8217 parseDirectiveDtpRelDWord();
8218 return false;
8219 }
8220
8221 if (IDVal == ".tprelword") {
8222 parseDirectiveTpRelWord();
8223 return false;
8224 }
8225
8226 if (IDVal == ".tpreldword") {
8227 parseDirectiveTpRelDWord();
8228 return false;
8229 }
8230
Jack Carter07c818d2013-01-25 01:31:34 +00008231 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00008232 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00008233 return false;
8234 }
8235
Scott Egertond1aeb052016-02-15 16:11:51 +00008236 if (IDVal == ".hword") {
8237 parseDataDirective(2, DirectiveID.getLoc());
8238 return false;
8239 }
8240
Nirav Dave996fc132016-05-05 14:15:46 +00008241 if (IDVal == ".option") {
8242 parseDirectiveOption();
8243 return false;
8244 }
Jack Carter0cd3c192014-01-06 23:27:31 +00008245
8246 if (IDVal == ".abicalls") {
8247 getTargetStreamer().emitDirectiveAbiCalls();
8248 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00008249 Error(Parser.getTok().getLoc(),
8250 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00008251 }
8252 return false;
8253 }
8254
Nirav Dave996fc132016-05-05 14:15:46 +00008255 if (IDVal == ".cpsetup") {
8256 parseDirectiveCPSetup();
8257 return false;
8258 }
8259 if (IDVal == ".cpreturn") {
8260 parseDirectiveCPReturn();
8261 return false;
8262 }
8263 if (IDVal == ".module") {
8264 parseDirectiveModule();
8265 return false;
8266 }
8267 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
8268 parseInternalDirectiveReallowModule();
8269 return false;
8270 }
8271 if (IDVal == ".insn") {
8272 parseInsnDirective();
8273 return false;
8274 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00008275 if (IDVal == ".rdata") {
8276 parseRSectionDirective(".rodata");
8277 return false;
8278 }
Nirav Dave996fc132016-05-05 14:15:46 +00008279 if (IDVal == ".sbss") {
8280 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
8281 return false;
8282 }
8283 if (IDVal == ".sdata") {
8284 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
8285 return false;
8286 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00008287
Rafael Espindola870c4e92012-01-11 03:56:41 +00008288 return true;
8289}
8290
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00008291bool MipsAsmParser::parseInternalDirectiveReallowModule() {
8292 // If this is not the end of the statement, report an error.
8293 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8294 reportParseError("unexpected token, expected end of statement");
8295 return false;
8296 }
8297
8298 getTargetStreamer().reallowModuleDirective();
8299
8300 getParser().Lex(); // Eat EndOfStatement token.
8301 return false;
8302}
8303
Rafael Espindola870c4e92012-01-11 03:56:41 +00008304extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00008305 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
8306 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
8307 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
8308 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00008309}
Jack Carterb4dbc172012-09-05 23:34:03 +00008310
8311#define GET_REGISTER_MATCHER
8312#define GET_MATCHER_IMPLEMENTATION
8313#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00008314
8315bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
8316 // Find the appropriate table for this asm variant.
8317 const MatchEntry *Start, *End;
8318 switch (VariantID) {
8319 default: llvm_unreachable("invalid variant!");
8320 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
8321 }
8322 // Search the table.
8323 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
8324 return MnemonicRange.first != MnemonicRange.second;
8325}