blob: 927b15e916f5b853830262deba8508034fb5b567 [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//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Rafael Espindola870c4e92012-01-11 03:56:41 +00006//
7//===----------------------------------------------------------------------===//
8
Eugene Zelenkodde94e42017-01-30 23:21:32 +00009#include "MCTargetDesc/MipsABIFlagsSection.h"
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000011#include "MCTargetDesc/MipsBaseInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000012#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000013#include "MCTargetDesc/MipsMCTargetDesc.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000014#include "MipsTargetStreamer.h"
Zoran Jovanovic375b60d2017-05-30 09:33:43 +000015#include "llvm/ADT/APFloat.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000016#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000017#include "llvm/ADT/SmallVector.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000018#include "llvm/ADT/StringRef.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/StringSwitch.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000020#include "llvm/ADT/Triple.h"
21#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000022#include "llvm/BinaryFormat/ELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000023#include "llvm/MC/MCContext.h"
24#include "llvm/MC/MCExpr.h"
25#include "llvm/MC/MCInst.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000026#include "llvm/MC/MCInstrDesc.h"
27#include "llvm/MC/MCObjectFileInfo.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000028#include "llvm/MC/MCParser/MCAsmLexer.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000029#include "llvm/MC/MCParser/MCAsmParser.h"
30#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Simon Atanasyanaf40d432019-03-19 15:15:35 +000031#include "llvm/MC/MCParser/MCAsmParserUtils.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"
Vladimir Stefanovic4433f932018-12-10 15:07:36 +000042#include "llvm/Support/CommandLine.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000043#include "llvm/Support/Compiler.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000044#include "llvm/Support/Debug.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000045#include "llvm/Support/ErrorHandling.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000046#include "llvm/Support/MathExtras.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000047#include "llvm/Support/SMLoc.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000048#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000049#include "llvm/Support/TargetRegistry.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000050#include "llvm/Support/raw_ostream.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000051#include <algorithm>
52#include <cassert>
53#include <cstdint>
Toma Tabacu9db22db2014-09-09 10:15:38 +000054#include <memory>
Eugene Zelenkodde94e42017-01-30 23:21:32 +000055#include <string>
56#include <utility>
Rafael Espindola870c4e92012-01-11 03:56:41 +000057
58using namespace llvm;
59
Chandler Carruthe96dd892014-04-21 22:55:11 +000060#define DEBUG_TYPE "mips-asm-parser"
61
Joey Gouly0e76fa72013-09-12 10:28:05 +000062namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000063
Joey Gouly0e76fa72013-09-12 10:28:05 +000064class MCInstrInfo;
Eugene Zelenkodde94e42017-01-30 23:21:32 +000065
66} // end namespace llvm
Joey Gouly0e76fa72013-09-12 10:28:05 +000067
Vladimir Stefanovic3daf8bc2019-01-17 21:50:37 +000068extern cl::opt<bool> EmitJalrReloc;
Vladimir Stefanovic4433f932018-12-10 15:07:36 +000069
Rafael Espindola870c4e92012-01-11 03:56:41 +000070namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000071
Jack Carter0b744b32012-10-04 02:29:46 +000072class MipsAssemblerOptions {
73public:
Eugene Zelenkodde94e42017-01-30 23:21:32 +000074 MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000075
Toma Tabacu9db22db2014-09-09 10:15:38 +000076 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000077 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000078 Reorder = Opts->isReorder();
79 Macro = Opts->isMacro();
80 Features = Opts->getFeatures();
81 }
82
Toma Tabacub19cf202015-04-27 13:12:59 +000083 unsigned getATRegIndex() const { return ATReg; }
84 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000085 if (Reg > 31)
86 return false;
87
88 ATReg = Reg;
89 return true;
90 }
Jack Carter0b744b32012-10-04 02:29:46 +000091
Toma Tabacu9db22db2014-09-09 10:15:38 +000092 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000093 void setReorder() { Reorder = true; }
94 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000095
Toma Tabacu9db22db2014-09-09 10:15:38 +000096 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000097 void setMacro() { Macro = true; }
98 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000099
Toma Tabacu465acfd2015-06-09 13:33:26 +0000100 const FeatureBitset &getFeatures() const { return Features; }
101 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000102
Daniel Sandersf0df2212014-08-04 12:20:00 +0000103 // Set of features that are either architecture features or referenced
104 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
105 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
106 // The reason we need this mask is explained in the selectArch function.
107 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000108 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +0000109
Jack Carter0b744b32012-10-04 02:29:46 +0000110private:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000111 unsigned ATReg = 1;
112 bool Reorder = true;
113 bool Macro = true;
Toma Tabacu465acfd2015-06-09 13:33:26 +0000114 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +0000115};
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000116
117} // end anonymous namespace
Jack Carter0b744b32012-10-04 02:29:46 +0000118
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000119const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
120 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
121 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
122 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
123 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
124 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
125 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
126 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
127 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
128};
129
Jack Carter0b744b32012-10-04 02:29:46 +0000130namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000131
Rafael Espindola870c4e92012-01-11 03:56:41 +0000132class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000133 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000134 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000135 return static_cast<MipsTargetStreamer &>(TS);
136 }
137
Eric Christophera5762812015-01-26 17:33:46 +0000138 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000139 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000140 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
141 // nullptr, which indicates that no function is currently
142 // selected. This usually happens after an '.end func'
143 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000144 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000145 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000146 bool IsCpRestoreSet;
147 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000148 unsigned CpSaveLocation;
149 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
150 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000151
Simon Atanasyan69301c92018-05-29 15:58:06 +0000152 // Map of register aliases created via the .set directive.
153 StringMap<AsmToken> RegisterSets;
154
Daniel Sandersef638fe2014-10-03 15:37:37 +0000155 // Print a warning along with its fix-it message at the given range.
156 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
157 SMRange Range, bool ShowColors = true);
158
Simon Dardis6a319922018-05-25 16:15:48 +0000159 void ConvertXWPOperands(MCInst &Inst, const OperandVector &Operands);
160
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000161#define GET_ASSEMBLER_HEADER
162#include "MipsGenAsmMatcher.inc"
163
Daniel Sandersc5537422016-07-27 13:49:44 +0000164 unsigned
165 checkEarlyTargetMatchPredicate(MCInst &Inst,
166 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000167 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
168
Chad Rosier49963552012-10-13 00:26:04 +0000169 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000170 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000171 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000172 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000173
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000174 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000175 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000176
Toma Tabacu13964452014-09-04 13:23:44 +0000177 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000178
Toma Tabacu13964452014-09-04 13:23:44 +0000179 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000180
Craig Topper55bc6cb2017-02-08 02:54:12 +0000181 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
182
David Blaikie960ea3f2014-06-08 16:18:35 +0000183 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
184 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000185
Craig Topper56c590a2014-04-29 07:58:02 +0000186 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000187
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000188 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
189 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000190 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000191 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000192 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
Simon Atanasyan69301c92018-05-29 15:58:06 +0000193 const AsmToken &Token,
194 SMLoc S);
195 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000196 SMLoc S);
197 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
198 OperandMatchResultTy parseImm(OperandVector &Operands);
199 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
200 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000201 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000202
David Blaikie960ea3f2014-06-08 16:18:35 +0000203 bool searchSymbolAlias(OperandVector &Operands);
204
Toma Tabacu13964452014-09-04 13:23:44 +0000205 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000206
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000207 enum MacroExpanderResultTy {
208 MER_NotAMacro,
209 MER_Success,
210 MER_Fail,
211 };
Jack Carter30a59822012-10-04 04:03:53 +0000212
Matheus Almeida3813d572014-06-19 14:39:14 +0000213 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000214 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
215 MCStreamer &Out,
216 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000217
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
219 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000220
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000221 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000222 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000223 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000224
Toma Tabacuf712ede2015-06-17 14:31:51 +0000225 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
226 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000227 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000228
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000229 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
230
Toma Tabacu00e98672015-05-01 12:19:27 +0000231 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000232 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000233
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000234 bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU,
235 SMLoc IDLoc, MCStreamer &Out,
236 const MCSubtargetInfo *STI);
237
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000238 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
239 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000240 SMLoc IDLoc, MCStreamer &Out,
241 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000242
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000243 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000245
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000246 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Simon Atanasyana1882672018-05-24 07:36:11 +0000247 const MCSubtargetInfo *STI, bool IsLoad);
Daniel Sandersfba875f2016-04-29 13:43:45 +0000248
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000249 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
250 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000251
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000252 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
253 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000254
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000255 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
256 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000257
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000258 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
259 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000260
Stefan Maksimovic0a239982018-07-09 13:06:44 +0000261 bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
262 const MCSubtargetInfo *STI, const bool IsMips64,
263 const bool Signed);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000264
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000265 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000266 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000267
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000268 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
269 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000270
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000271 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
272 const MCSubtargetInfo *STI);
273
274 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000275 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000276
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000277 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000278 MCStreamer &Out, const MCSubtargetInfo *STI);
279 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
280 const MCSubtargetInfo *STI);
281 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
282 const MCSubtargetInfo *STI);
283 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
284 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000285
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000286 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
287 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000288
Simon Dardis3c82a642017-02-08 16:25:05 +0000289 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
290 const MCSubtargetInfo *STI);
291
292 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
293 const MCSubtargetInfo *STI);
294
295 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
296 const MCSubtargetInfo *STI);
297
298 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
299 const MCSubtargetInfo *STI);
300
Simon Dardisaff4d142016-10-18 14:28:00 +0000301 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
302 const MCSubtargetInfo *STI, bool IsLoad);
303
Simon Dardis43115a12016-11-21 20:30:41 +0000304 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
305 const MCSubtargetInfo *STI);
306
307 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
308 const MCSubtargetInfo *STI);
309
Simon Dardisde5ed0c2017-11-14 22:26:42 +0000310 bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
311 const MCSubtargetInfo *STI);
312
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000313 bool reportParseError(Twine ErrorMsg);
314 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000315
Jack Carterb5cf5902013-04-17 00:18:04 +0000316 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000317
318 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000319 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000320 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000321 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000322 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000323 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000324 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000325 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000326 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000327 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000328 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000329 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000330 bool parseInsnDirective();
Simon Dardis1c73fcc2017-06-22 10:41:51 +0000331 bool parseRSectionDirective(StringRef Section);
Simon Atanasyanbe186202016-02-11 06:45:54 +0000332 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000333
334 bool parseSetAtDirective();
335 bool parseSetNoAtDirective();
336 bool parseSetMacroDirective();
337 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000338 bool parseSetMsaDirective();
339 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000340 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000341 bool parseSetReorderDirective();
342 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000343 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000344 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000345 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000346 bool parseSetOddSPRegDirective();
347 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000348 bool parseSetPopDirective();
349 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000350 bool parseSetSoftFloatDirective();
351 bool parseSetHardFloatDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +0000352 bool parseSetMtDirective();
353 bool parseSetNoMtDirective();
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000354 bool parseSetNoCRCDirective();
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000355 bool parseSetNoVirtDirective();
Petar Jovanovicdaf51692018-05-17 16:30:32 +0000356 bool parseSetNoGINVDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000357
Jack Carterd76b2372013-03-21 21:44:16 +0000358 bool parseSetAssignment();
359
Vladimir Medic4c299852013-11-06 11:27:05 +0000360 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000361 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000362 bool parseDirectiveDtpRelWord();
363 bool parseDirectiveDtpRelDWord();
364 bool parseDirectiveTpRelWord();
365 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000366 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000367 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000368 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
369 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000370
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000371 bool parseInternalDirectiveReallowModule();
372
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000373 bool eatComma(StringRef ErrorStr);
374
Jack Carter1ac53222013-02-20 23:11:17 +0000375 int matchCPURegisterName(StringRef Symbol);
376
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000377 int matchHWRegsRegisterName(StringRef Symbol);
378
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000379 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000380
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000381 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000382
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000383 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000384
Jack Carter5dc8ac92013-09-25 23:50:44 +0000385 int matchMSA128RegisterName(StringRef Name);
386
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000387 int matchMSA128CtrlRegisterName(StringRef Name);
388
Jack Carterd0bd6422013-04-18 00:41:53 +0000389 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000390
Toma Tabacu89a712b2015-04-15 10:48:56 +0000391 /// Returns the internal register number for the current AT. Also checks if
392 /// the current AT is unavailable (set to $0) and gives an error if it is.
393 /// This should be used in pseudo-instruction expansions which need AT.
394 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000395
Simon Dardis3aa8a902017-02-06 12:43:46 +0000396 bool canUseATReg();
397
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000398 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
399 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000400
401 // Helper function that checks if the value of a vector index is within the
402 // boundaries of accepted values for each RegisterKind
403 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
404 bool validateMSAIndex(int Val, int RegKind);
405
Daniel Sandersf0df2212014-08-04 12:20:00 +0000406 // Selects a new architecture by updating the FeatureBits with the necessary
407 // info including implied dependencies.
408 // Internally, it clears all the feature bits related to *any* architecture
409 // and selects the new one using the ToggleFeature functionality of the
410 // MCSubtargetInfo object that handles implied dependencies. The reason we
411 // clear all the arch related bits manually is because ToggleFeature only
412 // clears the features that imply the feature being cleared and not the
413 // features implied by the feature being cleared. This is easier to see
414 // with an example:
415 // --------------------------------------------------
416 // | Feature | Implies |
417 // | -------------------------------------------------|
418 // | FeatureMips1 | None |
419 // | FeatureMips2 | FeatureMips1 |
420 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
421 // | FeatureMips4 | FeatureMips3 |
422 // | ... | |
423 // --------------------------------------------------
424 //
425 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
426 // FeatureMipsGP64 | FeatureMips1)
427 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
428 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000429 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000430 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000431 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
432 STI.setFeatureBits(FeatureBits);
433 setAvailableFeatures(
434 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000435 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000436 }
437
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000438 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000439 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000440 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000441 setAvailableFeatures(
442 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000443 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000444 }
445 }
446
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000447 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000448 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000449 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000450 setAvailableFeatures(
451 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000452 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000453 }
454 }
455
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000456 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
457 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000458 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000459 }
460
461 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
462 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000463 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000464 }
465
Rafael Espindola870c4e92012-01-11 03:56:41 +0000466public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000467 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000468 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000469 Match_RequiresDifferentOperands,
470 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000471 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000472 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000473 Match_NonZeroOperandForSync,
Simon Dardis52ae4f02018-03-07 11:39:48 +0000474 Match_NonZeroOperandForMTCX,
Simon Dardis6f83ae32017-09-14 15:17:50 +0000475 Match_RequiresPosSizeRange0_32,
476 Match_RequiresPosSizeRange33_64,
Simon Dardis55e44672017-09-14 17:27:53 +0000477 Match_RequiresPosSizeUImm6,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000478#define GET_OPERAND_DIAGNOSTIC_TYPES
479#include "MipsGenAsmMatcher.inc"
480#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000481 };
482
Akira Hatanakab11ef082015-11-14 06:35:56 +0000483 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000484 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000485 : MCTargetAsmParser(Options, sti, MII),
Daniel Sanders50f17232015-09-15 16:17:27 +0000486 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
487 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000488 MCAsmParserExtension::Initialize(parser);
489
Toma Tabacu11e14a92015-04-21 11:50:52 +0000490 parser.addAliasForDirective(".asciiz", ".asciz");
Simon Atanasyanb5244592018-07-25 07:07:43 +0000491 parser.addAliasForDirective(".hword", ".2byte");
492 parser.addAliasForDirective(".word", ".4byte");
493 parser.addAliasForDirective(".dword", ".8byte");
Toma Tabacu11e14a92015-04-21 11:50:52 +0000494
Jack Carterb4dbc172012-09-05 23:34:03 +0000495 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000496 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000497
Toma Tabacu9db22db2014-09-09 10:15:38 +0000498 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000499 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000500 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000501
Toma Tabacu9db22db2014-09-09 10:15:38 +0000502 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000503 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000504 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000505
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000506 getTargetStreamer().updateABIInfo(*this);
507
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000508 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000509 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000510
511 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000512
Rafael Espindola699281c2016-05-18 11:58:50 +0000513 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000514
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000515 IsCpRestoreSet = false;
516 CpRestoreOffset = -1;
517
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000518 const Triple &TheTriple = sti.getTargetTriple();
Alexander Richardson85e200e2018-06-25 16:49:20 +0000519 IsLittleEndian = TheTriple.isLittleEndian();
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +0000520
521 if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
522 report_fatal_error("microMIPS64R6 is not supported", false);
Simon Dardisaf38a8f2018-06-19 16:05:44 +0000523
524 if (!isABI_O32() && inMicroMipsMode())
525 report_fatal_error("microMIPS64 is not supported", false);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000526 }
527
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000528 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
529 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
530
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000531 bool isGP64bit() const {
532 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
533 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000534
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000535 bool isFP64bit() const {
536 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
537 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000538
Eric Christophera5762812015-01-26 17:33:46 +0000539 const MipsABIInfo &getABI() const { return ABI; }
540 bool isABI_N32() const { return ABI.IsN32(); }
541 bool isABI_N64() const { return ABI.IsN64(); }
542 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000543 bool isABI_FPXX() const {
544 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
545 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000546
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000547 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000548 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000549 }
550
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000551 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000552 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000553 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000554
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000555 bool hasMips1() const {
556 return getSTI().getFeatureBits()[Mips::FeatureMips1];
557 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000558
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000559 bool hasMips2() const {
560 return getSTI().getFeatureBits()[Mips::FeatureMips2];
561 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000562
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000563 bool hasMips3() const {
564 return getSTI().getFeatureBits()[Mips::FeatureMips3];
565 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000566
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000567 bool hasMips4() const {
568 return getSTI().getFeatureBits()[Mips::FeatureMips4];
569 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000570
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000571 bool hasMips5() const {
572 return getSTI().getFeatureBits()[Mips::FeatureMips5];
573 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000574
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000575 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000576 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000577 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000578
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000579 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000580 return getSTI().getFeatureBits()[Mips::FeatureMips64];
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 hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000584 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
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 hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000588 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000589 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000590
Daniel Sanders17793142015-02-18 16:24:50 +0000591 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000592 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000593 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000594
Daniel Sanders17793142015-02-18 16:24:50 +0000595 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000596 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
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 hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000600 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
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 hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000604 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000605 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000606
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000607 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000608 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000609 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000610
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000611 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000612 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000613 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000614
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000615 bool hasDSP() const {
616 return getSTI().getFeatureBits()[Mips::FeatureDSP];
617 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000618
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000619 bool hasDSPR2() const {
620 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
621 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000622
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000623 bool hasDSPR3() const {
624 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
625 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000626
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000627 bool hasMSA() const {
628 return getSTI().getFeatureBits()[Mips::FeatureMSA];
629 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000630
Kai Nackee0245392015-01-27 19:11:28 +0000631 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000632 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000633 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000634
Daniel Sandersa6994442015-08-18 12:33:54 +0000635 bool inPicMode() {
636 return IsPicEnabled;
637 }
638
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000639 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000640 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000641 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000642
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000643 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000644 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000645 }
646
Eric Christophere8ae3e32015-05-07 23:10:21 +0000647 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000648 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000649 }
Simon Dardisae719c52017-07-11 18:03:20 +0000650 bool hasMT() const {
651 return getSTI().getFeatureBits()[Mips::FeatureMT];
652 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000653
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000654 bool hasCRC() const {
655 return getSTI().getFeatureBits()[Mips::FeatureCRC];
656 }
657
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000658 bool hasVirt() const {
659 return getSTI().getFeatureBits()[Mips::FeatureVirt];
660 }
661
Petar Jovanovicdaf51692018-05-17 16:30:32 +0000662 bool hasGINV() const {
663 return getSTI().getFeatureBits()[Mips::FeatureGINV];
664 }
665
Toma Tabacud9d344b2015-04-27 14:05:04 +0000666 /// Warn if RegIndex is the same as the current AT.
667 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000668
669 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000670
671 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000672
673 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
674 AsmToken::TokenKind OperatorToken,
675 MCContext &Ctx) override {
676 switch(OperatorToken) {
677 default:
678 llvm_unreachable("Unknown token");
679 return nullptr;
680 case AsmToken::PercentCall16:
681 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
682 case AsmToken::PercentCall_Hi:
683 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
684 case AsmToken::PercentCall_Lo:
685 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
686 case AsmToken::PercentDtprel_Hi:
687 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
688 case AsmToken::PercentDtprel_Lo:
689 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
690 case AsmToken::PercentGot:
691 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
692 case AsmToken::PercentGot_Disp:
693 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
694 case AsmToken::PercentGot_Hi:
695 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
696 case AsmToken::PercentGot_Lo:
697 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
698 case AsmToken::PercentGot_Ofst:
699 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
700 case AsmToken::PercentGot_Page:
701 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
702 case AsmToken::PercentGottprel:
703 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
704 case AsmToken::PercentGp_Rel:
705 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
706 case AsmToken::PercentHi:
707 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
708 case AsmToken::PercentHigher:
709 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
710 case AsmToken::PercentHighest:
711 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
712 case AsmToken::PercentLo:
713 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
714 case AsmToken::PercentNeg:
715 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
716 case AsmToken::PercentPcrel_Hi:
717 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
718 case AsmToken::PercentPcrel_Lo:
719 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
720 case AsmToken::PercentTlsgd:
721 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
722 case AsmToken::PercentTlsldm:
723 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
724 case AsmToken::PercentTprel_Hi:
725 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
726 case AsmToken::PercentTprel_Lo:
727 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
728 }
729 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000730};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000731
732/// MipsOperand - Instances of this class represent a parsed Mips machine
733/// instruction.
734class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000735public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000736 /// Broad categories of register classes
737 /// The exact class is finalized by the render method.
738 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000739 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000740 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000741 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000742 RegKind_FCC = 4, /// FCC
743 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
744 RegKind_MSACtrl = 16, /// MSA control registers
745 RegKind_COP2 = 32, /// COP2
746 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
747 /// context).
748 RegKind_CCR = 128, /// CCR
749 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000750 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000751 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000752 /// Potentially any (e.g. $1)
753 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
754 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000755 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000756 };
757
758private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000759 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000760 k_Immediate, /// An immediate (possibly involving symbol references)
761 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000762 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000763 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000764 k_RegList, /// A physical register list
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000765 } Kind;
766
David Blaikie960ea3f2014-06-08 16:18:35 +0000767public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000768 MipsOperand(KindTy K, MipsAsmParser &Parser)
769 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
770
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000771 ~MipsOperand() override {
772 switch (Kind) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000773 case k_Memory:
774 delete Mem.Base;
775 break;
776 case k_RegList:
777 delete RegList.List;
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000778 break;
779 case k_Immediate:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000780 case k_RegisterIndex:
781 case k_Token:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000782 break;
783 }
784 }
785
David Blaikie960ea3f2014-06-08 16:18:35 +0000786private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000787 /// For diagnostics, and checking the assembler temporary
788 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000789
Eric Christopher8996c5d2013-03-15 00:42:55 +0000790 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000791 const char *Data;
792 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000793 };
794
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000795 struct RegIdxOp {
796 unsigned Index; /// Index into the register class
797 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000798 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000799 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000800 };
801
802 struct ImmOp {
803 const MCExpr *Val;
804 };
805
806 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000807 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000808 const MCExpr *Off;
809 };
810
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000811 struct RegListOp {
812 SmallVector<unsigned, 10> *List;
813 };
814
Jack Carterb4dbc172012-09-05 23:34:03 +0000815 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000816 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000817 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000818 struct ImmOp Imm;
819 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000820 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000821 };
822
823 SMLoc StartLoc, EndLoc;
824
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000825 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000826 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
827 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000828 const MCRegisterInfo *RegInfo,
829 SMLoc S, SMLoc E,
830 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000831 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000832 Op->RegIdx.Index = Index;
833 Op->RegIdx.RegInfo = RegInfo;
834 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000835 Op->RegIdx.Tok.Data = Str.data();
836 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000837 Op->StartLoc = S;
838 Op->EndLoc = E;
839 return Op;
840 }
841
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000842public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000843 /// Coerce the register to GPR32 and return the real register for the current
844 /// target.
845 unsigned getGPR32Reg() const {
846 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000847 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000848 unsigned ClassID = Mips::GPR32RegClassID;
849 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000850 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000851
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000852 /// Coerce the register to GPR32 and return the real register for the current
853 /// target.
854 unsigned getGPRMM16Reg() const {
855 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
856 unsigned ClassID = Mips::GPR32RegClassID;
857 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
858 }
859
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000860 /// Coerce the register to GPR64 and return the real register for the current
861 /// target.
862 unsigned getGPR64Reg() const {
863 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
864 unsigned ClassID = Mips::GPR64RegClassID;
865 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000866 }
867
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000868private:
869 /// Coerce the register to AFGR64 and return the real register for the current
870 /// target.
871 unsigned getAFGR64Reg() const {
872 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
873 if (RegIdx.Index % 2 != 0)
874 AsmParser.Warning(StartLoc, "Float register should be even.");
875 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
876 .getRegister(RegIdx.Index / 2);
877 }
878
879 /// Coerce the register to FGR64 and return the real register for the current
880 /// target.
881 unsigned getFGR64Reg() const {
882 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
883 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
884 .getRegister(RegIdx.Index);
885 }
886
887 /// Coerce the register to FGR32 and return the real register for the current
888 /// target.
889 unsigned getFGR32Reg() const {
890 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
891 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
892 .getRegister(RegIdx.Index);
893 }
894
895 /// Coerce the register to FGRH32 and return the real register for the current
896 /// target.
897 unsigned getFGRH32Reg() const {
898 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
899 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
900 .getRegister(RegIdx.Index);
901 }
902
903 /// Coerce the register to FCC and return the real register for the current
904 /// target.
905 unsigned getFCCReg() const {
906 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
907 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
908 .getRegister(RegIdx.Index);
909 }
910
911 /// Coerce the register to MSA128 and return the real register for the current
912 /// target.
913 unsigned getMSA128Reg() const {
914 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
915 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
916 // identical
917 unsigned ClassID = Mips::MSA128BRegClassID;
918 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
919 }
920
921 /// Coerce the register to MSACtrl and return the real register for the
922 /// current target.
923 unsigned getMSACtrlReg() const {
924 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
925 unsigned ClassID = Mips::MSACtrlRegClassID;
926 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
927 }
928
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000929 /// Coerce the register to COP0 and return the real register for the
930 /// current target.
931 unsigned getCOP0Reg() const {
932 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
933 unsigned ClassID = Mips::COP0RegClassID;
934 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
935 }
936
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000937 /// Coerce the register to COP2 and return the real register for the
938 /// current target.
939 unsigned getCOP2Reg() const {
940 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
941 unsigned ClassID = Mips::COP2RegClassID;
942 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
943 }
944
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000945 /// Coerce the register to COP3 and return the real register for the
946 /// current target.
947 unsigned getCOP3Reg() const {
948 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
949 unsigned ClassID = Mips::COP3RegClassID;
950 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
951 }
952
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000953 /// Coerce the register to ACC64DSP and return the real register for the
954 /// current target.
955 unsigned getACC64DSPReg() const {
956 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
957 unsigned ClassID = Mips::ACC64DSPRegClassID;
958 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
959 }
960
961 /// Coerce the register to HI32DSP and return the real register for the
962 /// current target.
963 unsigned getHI32DSPReg() const {
964 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
965 unsigned ClassID = Mips::HI32DSPRegClassID;
966 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
967 }
968
969 /// Coerce the register to LO32DSP and return the real register for the
970 /// current target.
971 unsigned getLO32DSPReg() const {
972 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
973 unsigned ClassID = Mips::LO32DSPRegClassID;
974 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
975 }
976
977 /// Coerce the register to CCR and return the real register for the
978 /// current target.
979 unsigned getCCRReg() const {
980 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
981 unsigned ClassID = Mips::CCRRegClassID;
982 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
983 }
984
985 /// Coerce the register to HWRegs and return the real register for the
986 /// current target.
987 unsigned getHWRegsReg() const {
988 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
989 unsigned ClassID = Mips::HWRegsRegClassID;
990 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
991 }
992
993public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000994 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000995 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000996 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000997 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000998 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000999 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +00001000 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001001 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001002 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001003
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001004 void addRegOperands(MCInst &Inst, unsigned N) const {
1005 llvm_unreachable("Use a custom parser instead");
1006 }
1007
Daniel Sanders21bce302014-04-01 12:35:23 +00001008 /// Render the operand to an MCInst as a GPR32
1009 /// Asserts if the wrong number of operands are requested, or the operand
1010 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +00001011 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1012 assert(N == 1 && "Invalid number of operands!");
1013 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1014 }
1015
1016 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1017 assert(N == 1 && "Invalid number of operands!");
1018 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1019 }
1020
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001021 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1022 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001023 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001024 }
1025
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001026 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
1027 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001028 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001029 }
1030
Jozef Kolek1904fa22014-11-24 14:25:53 +00001031 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1032 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001033 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001034 }
1035
Zoran Jovanovic41688672015-02-10 16:36:20 +00001036 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1037 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001038 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001039 }
1040
Simon Atanasyan852dd832018-09-19 18:46:21 +00001041 void addGPRMM16AsmRegMovePPairFirstOperands(MCInst &Inst, unsigned N) const {
1042 assert(N == 1 && "Invalid number of operands!");
1043 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
1044 }
1045
1046 void addGPRMM16AsmRegMovePPairSecondOperands(MCInst &Inst,
1047 unsigned N) const {
1048 assert(N == 1 && "Invalid number of operands!");
1049 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
1050 }
1051
Daniel Sanders21bce302014-04-01 12:35:23 +00001052 /// Render the operand to an MCInst as a GPR64
1053 /// Asserts if the wrong number of operands are requested, or the operand
1054 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001055 void addGPR64AsmRegOperands(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(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001058 }
1059
1060 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1061 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001062 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001063 }
1064
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001065 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1066 assert(N == 1 && "Invalid number of operands!");
1067 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1068 }
1069
1070 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1071 assert(N == 1 && "Invalid number of operands!");
1072 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1073 }
1074
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001075 void addFGR64AsmRegOperands(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(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001078 }
1079
1080 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1081 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001082 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001083 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001084 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001085 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001086 AsmParser.getParser().printError(
1087 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1088 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001089 }
1090
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001091 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1092 assert(N == 1 && "Invalid number of operands!");
1093 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1094 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1095 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1096 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1097 "registers");
1098 }
1099
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001100 void addFGRH32AsmRegOperands(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(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001103 }
1104
1105 void addFCCAsmRegOperands(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(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 }
1109
1110 void addMSA128AsmRegOperands(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(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001113 }
1114
1115 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1116 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001117 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001118 }
1119
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001120 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1121 assert(N == 1 && "Invalid number of operands!");
1122 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1123 }
1124
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001125 void addCOP2AsmRegOperands(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(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001128 }
1129
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001130 void addCOP3AsmRegOperands(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(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001133 }
1134
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001135 void addACC64DSPAsmRegOperands(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(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001138 }
1139
1140 void addHI32DSPAsmRegOperands(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(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001143 }
1144
1145 void addLO32DSPAsmRegOperands(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(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001148 }
1149
1150 void addCCRAsmRegOperands(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(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001153 }
1154
1155 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1156 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001157 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001158 }
1159
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001160 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001161 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1162 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001163 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001164 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001165 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001166 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001167 Inst.addOperand(MCOperand::createImm(Imm));
1168 }
1169
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001170 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001171 void addSImmOperands(MCInst &Inst, unsigned N) const {
1172 if (isImm() && !isConstantImm()) {
1173 addExpr(Inst, getImm());
1174 return;
1175 }
1176 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1177 }
1178
1179 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001180 void addUImmOperands(MCInst &Inst, unsigned N) const {
1181 if (isImm() && !isConstantImm()) {
1182 addExpr(Inst, getImm());
1183 return;
1184 }
1185 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1186 }
1187
Daniel Sanders78e89022016-03-11 11:37:50 +00001188 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1189 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1190 assert(N == 1 && "Invalid number of operands!");
1191 int64_t Imm = getConstantImm() - Offset;
1192 Imm = SignExtend64<Bits>(Imm);
1193 Imm += Offset;
1194 Imm += AdjustOffset;
1195 Inst.addOperand(MCOperand::createImm(Imm));
1196 }
1197
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001198 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001199 assert(N == 1 && "Invalid number of operands!");
1200 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001201 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001202 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001203
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001204 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001205 assert(N == 2 && "Invalid number of operands!");
1206
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001207 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1208 ? getMemBase()->getGPR64Reg()
1209 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001210
1211 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001212 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001213 }
1214
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001215 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1216 assert(N == 2 && "Invalid number of operands!");
1217
Jim Grosbache9119e42015-05-13 18:37:00 +00001218 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001219
1220 const MCExpr *Expr = getMemOff();
1221 addExpr(Inst, Expr);
1222 }
1223
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001224 void addRegListOperands(MCInst &Inst, unsigned N) const {
1225 assert(N == 1 && "Invalid number of operands!");
1226
1227 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001228 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001229 }
1230
Craig Topper56c590a2014-04-29 07:58:02 +00001231 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001232 // As a special case until we sort out the definition of div/divu, accept
1233 // $0/$zero here so that MCK_ZERO works correctly.
1234 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001235 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001236
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001237 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001238 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001239
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001240 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001241 int64_t Res;
1242 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001243 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001244
Daniel Sanders52da7af2015-11-06 12:11:03 +00001245 bool isConstantImmz() const {
1246 return isConstantImm() && getConstantImm() == 0;
1247 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001248
Daniel Sandersea4f6532015-11-06 12:22:31 +00001249 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1250 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1251 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001252
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001253 template <unsigned Bits> bool isSImm() const {
1254 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1255 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001256
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001257 template <unsigned Bits> bool isUImm() const {
1258 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1259 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001260
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001261 template <unsigned Bits> bool isAnyImm() const {
1262 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1263 isUInt<Bits>(getConstantImm()))
1264 : isImm();
1265 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001266
Daniel Sanders78e89022016-03-11 11:37:50 +00001267 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1268 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001269 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001270
Hrvoje Varga46458d02016-02-25 12:53:29 +00001271 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1272 return isConstantImm() && getConstantImm() >= Bottom &&
1273 getConstantImm() <= Top;
1274 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001275
Craig Topper56c590a2014-04-29 07:58:02 +00001276 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001277 // Note: It's not possible to pretend that other operand kinds are tokens.
1278 // The matcher emitter checks tokens first.
1279 return Kind == k_Token;
1280 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001281
Craig Topper56c590a2014-04-29 07:58:02 +00001282 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001283
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001284 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001285 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001286 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001287
Simon Dardis4ccda502016-05-27 13:56:36 +00001288 // Allow relocation operators.
1289 // FIXME: This predicate and others need to look through binary expressions
1290 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001291 template <unsigned Bits, unsigned ShiftAmount = 0>
1292 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001293 if (!isMem())
1294 return false;
1295 if (!getMemBase()->isGPRAsmReg())
1296 return false;
1297 if (isa<MCTargetExpr>(getMemOff()) ||
1298 (isConstantMemOff() &&
1299 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1300 return true;
1301 MCValue Res;
1302 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1303 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001304 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001305
Simon Atanasyand4d892f2018-04-26 19:55:28 +00001306 bool isMemWithPtrSizeOffset() const {
1307 if (!isMem())
1308 return false;
1309 if (!getMemBase()->isGPRAsmReg())
1310 return false;
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00001311 const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32;
Simon Atanasyand4d892f2018-04-26 19:55:28 +00001312 if (isa<MCTargetExpr>(getMemOff()) ||
1313 (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))
1314 return true;
1315 MCValue Res;
1316 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1317 return IsReloc && isIntN(PtrBits, Res.getConstant());
1318 }
1319
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001320 bool isMemWithGRPMM16Base() const {
1321 return isMem() && getMemBase()->isMM16AsmReg();
1322 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001323
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001324 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1325 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1326 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1327 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001328
Jozef Kolek12c69822014-12-23 16:16:33 +00001329 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1330 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1331 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1332 && (getMemBase()->getGPR32Reg() == Mips::SP);
1333 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001334
Daniel Sanderse473dc92016-05-09 13:38:25 +00001335 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1336 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1337 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1338 && (getMemBase()->getGPR32Reg() == Mips::GP);
1339 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001340
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001341 template <unsigned Bits, unsigned ShiftLeftAmount>
1342 bool isScaledUImm() const {
1343 return isConstantImm() &&
1344 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001345 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001346
Daniel Sanders97297772016-03-22 14:40:00 +00001347 template <unsigned Bits, unsigned ShiftLeftAmount>
1348 bool isScaledSImm() const {
Simon Atanasyan478220f2018-05-24 07:36:00 +00001349 if (isConstantImm() &&
1350 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001351 return true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00001352 // Operand can also be a symbol or symbol plus
1353 // offset in case of relocations.
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001354 if (Kind != k_Immediate)
1355 return false;
1356 MCValue Res;
1357 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1358 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001359 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001360
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001361 bool isRegList16() const {
1362 if (!isRegList())
1363 return false;
1364
1365 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001366 if (Size < 2 || Size > 5)
1367 return false;
1368
1369 unsigned R0 = RegList.List->front();
1370 unsigned R1 = RegList.List->back();
1371 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1372 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001373 return false;
1374
1375 int PrevReg = *RegList.List->begin();
1376 for (int i = 1; i < Size - 1; i++) {
1377 int Reg = (*(RegList.List))[i];
1378 if ( Reg != PrevReg + 1)
1379 return false;
1380 PrevReg = Reg;
1381 }
1382
1383 return true;
1384 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001385
Vladimir Medic2b953d02013-10-01 09:48:56 +00001386 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001387
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001388 bool isLSAImm() const {
1389 if (!isConstantImm())
1390 return false;
1391 int64_t Val = getConstantImm();
1392 return 1 <= Val && Val <= 4;
1393 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001394
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001395 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001396
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001397 StringRef getToken() const {
1398 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001399 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001400 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001401
Craig Topper56c590a2014-04-29 07:58:02 +00001402 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001403 // As a special case until we sort out the definition of div/divu, accept
1404 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001405 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1406 RegIdx.Kind & RegKind_GPR)
1407 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001408
Daniel Sanders976d9382016-07-05 13:38:40 +00001409 llvm_unreachable("Invalid access!");
1410 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001411 }
1412
Jack Carterb4dbc172012-09-05 23:34:03 +00001413 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001414 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001415 return Imm.Val;
1416 }
1417
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001418 int64_t getConstantImm() const {
1419 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001420 int64_t Value = 0;
1421 (void)Val->evaluateAsAbsolute(Value);
1422 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001423 }
1424
1425 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001426 assert((Kind == k_Memory) && "Invalid access!");
1427 return Mem.Base;
1428 }
1429
1430 const MCExpr *getMemOff() const {
1431 assert((Kind == k_Memory) && "Invalid access!");
1432 return Mem.Off;
1433 }
1434
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001435 int64_t getConstantMemOff() const {
1436 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1437 }
1438
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001439 const SmallVectorImpl<unsigned> &getRegList() const {
1440 assert((Kind == k_RegList) && "Invalid access!");
1441 return *(RegList.List);
1442 }
1443
David Blaikie960ea3f2014-06-08 16:18:35 +00001444 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1445 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001446 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001447 Op->Tok.Data = Str.data();
1448 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001449 Op->StartLoc = S;
1450 Op->EndLoc = S;
1451 return Op;
1452 }
1453
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001454 /// Create a numeric register (e.g. $1). The exact register remains
1455 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001456 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001457 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1458 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001459 LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001460 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001461 }
1462
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001463 /// Create a register that is definitely a GPR.
1464 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001465 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001466 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1467 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1468 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001469 }
1470
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001471 /// Create a register that is definitely a FGR.
1472 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001473 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001474 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1475 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1476 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001477 }
1478
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001479 /// Create a register that is definitely a HWReg.
1480 /// This is typically only used for named registers such as $hwr_cpunum.
1481 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001482 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001483 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001484 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001485 }
1486
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001487 /// Create a register that is definitely an FCC.
1488 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001489 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001490 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1491 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1492 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001493 }
1494
1495 /// Create a register that is definitely an ACC.
1496 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001497 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001498 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1499 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1500 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001501 }
1502
1503 /// Create a register that is definitely an MSA128.
1504 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001505 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001506 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1507 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1508 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001509 }
1510
1511 /// Create a register that is definitely an MSACtrl.
1512 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001513 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001514 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1515 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1516 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001517 }
1518
David Blaikie960ea3f2014-06-08 16:18:35 +00001519 static std::unique_ptr<MipsOperand>
1520 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001521 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001522 Op->Imm.Val = Val;
1523 Op->StartLoc = S;
1524 Op->EndLoc = E;
1525 return Op;
1526 }
1527
David Blaikie960ea3f2014-06-08 16:18:35 +00001528 static std::unique_ptr<MipsOperand>
1529 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1530 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001531 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001532 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001533 Op->Mem.Off = Off;
1534 Op->StartLoc = S;
1535 Op->EndLoc = E;
1536 return Op;
1537 }
1538
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001539 static std::unique_ptr<MipsOperand>
1540 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1541 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001542 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001543
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001544 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001545 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001546 Op->StartLoc = StartLoc;
1547 Op->EndLoc = EndLoc;
1548 return Op;
1549 }
1550
Simon Dardis509da1a2017-02-13 16:06:48 +00001551 bool isGPRZeroAsmReg() const {
1552 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1553 }
1554
1555 bool isGPRNonZeroAsmReg() const {
1556 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1557 RegIdx.Index <= 31;
1558 }
1559
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001560 bool isGPRAsmReg() const {
1561 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001562 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001563
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001564 bool isMM16AsmReg() const {
1565 if (!(isRegIdx() && RegIdx.Kind))
1566 return false;
1567 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1568 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001569
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001570 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001571 bool isMM16AsmRegZero() const {
1572 if (!(isRegIdx() && RegIdx.Kind))
1573 return false;
1574 return (RegIdx.Index == 0 ||
1575 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1576 RegIdx.Index == 17);
1577 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001578
Zoran Jovanovic41688672015-02-10 16:36:20 +00001579 bool isMM16AsmRegMoveP() const {
1580 if (!(isRegIdx() && RegIdx.Kind))
1581 return false;
1582 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1583 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1584 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001585
Simon Atanasyan852dd832018-09-19 18:46:21 +00001586 bool isMM16AsmRegMovePPairFirst() const {
1587 if (!(isRegIdx() && RegIdx.Kind))
1588 return false;
1589 return RegIdx.Index >= 4 && RegIdx.Index <= 6;
1590 }
1591
1592 bool isMM16AsmRegMovePPairSecond() const {
1593 if (!(isRegIdx() && RegIdx.Kind))
1594 return false;
1595 return (RegIdx.Index == 21 || RegIdx.Index == 22 ||
1596 (RegIdx.Index >= 5 && RegIdx.Index <= 7));
1597 }
1598
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001599 bool isFGRAsmReg() const {
1600 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1601 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001602 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001603
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001604 bool isStrictlyFGRAsmReg() const {
1605 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1606 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1607 }
1608
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001609 bool isHWRegsAsmReg() const {
1610 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001611 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001612
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001613 bool isCCRAsmReg() const {
1614 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001615 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001616
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001617 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001618 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1619 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001620 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001621 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001622
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001623 bool isACCAsmReg() const {
1624 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001625 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001626
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001627 bool isCOP0AsmReg() const {
1628 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1629 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001630
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001631 bool isCOP2AsmReg() const {
1632 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001633 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001634
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001635 bool isCOP3AsmReg() const {
1636 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1637 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001638
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001639 bool isMSA128AsmReg() const {
1640 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001641 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001642
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001643 bool isMSACtrlAsmReg() const {
1644 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001645 }
1646
Jack Carterb4dbc172012-09-05 23:34:03 +00001647 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001648 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001649 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001650 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001651
Craig Topper56c590a2014-04-29 07:58:02 +00001652 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001653 switch (Kind) {
1654 case k_Immediate:
1655 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001656 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001657 OS << ">";
1658 break;
1659 case k_Memory:
1660 OS << "Mem<";
1661 Mem.Base->print(OS);
1662 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001663 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001664 OS << ">";
1665 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001666 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001667 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1668 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001669 break;
1670 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001671 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001672 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001673 case k_RegList:
1674 OS << "RegList< ";
1675 for (auto Reg : (*RegList.List))
1676 OS << Reg << " ";
1677 OS << ">";
1678 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001679 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001680 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001681
1682 bool isValidForTie(const MipsOperand &Other) const {
1683 if (Kind != Other.Kind)
1684 return false;
1685
1686 switch (Kind) {
1687 default:
1688 llvm_unreachable("Unexpected kind");
1689 return false;
1690 case k_RegisterIndex: {
1691 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1692 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1693 return Token == OtherToken;
1694 }
1695 }
1696 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001697}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001698
1699} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001700
Jack Carter9e65aa32013-03-22 00:05:30 +00001701namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001702
Jack Carter9e65aa32013-03-22 00:05:30 +00001703extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001704
1705} // end namespace llvm
1706
Jack Carter9e65aa32013-03-22 00:05:30 +00001707static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1708 return MipsInsts[Opcode];
1709}
1710
Aleksandar Beserminji8abf6802019-01-09 15:58:02 +00001711static bool hasShortDelaySlot(MCInst &Inst) {
1712 switch (Inst.getOpcode()) {
1713 case Mips::BEQ_MM:
1714 case Mips::BNE_MM:
1715 case Mips::BLTZ_MM:
1716 case Mips::BGEZ_MM:
1717 case Mips::BLEZ_MM:
1718 case Mips::BGTZ_MM:
1719 case Mips::JRC16_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001720 case Mips::JALS_MM:
1721 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001722 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001723 case Mips::BGEZALS_MM:
1724 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001725 return true;
Aleksandar Beserminji8abf6802019-01-09 15:58:02 +00001726 case Mips::J_MM:
1727 return !Inst.getOperand(0).isReg();
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001728 default:
1729 return false;
1730 }
1731}
1732
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001733static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1734 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1735 return &SRExpr->getSymbol();
1736 }
1737
1738 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1739 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1740 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1741
1742 if (LHSSym)
1743 return LHSSym;
1744
1745 if (RHSSym)
1746 return RHSSym;
1747
1748 return nullptr;
1749 }
1750
1751 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1752 return getSingleMCSymbol(UExpr->getSubExpr());
1753
1754 return nullptr;
1755}
1756
1757static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1758 if (isa<MCSymbolRefExpr>(Expr))
1759 return 1;
1760
1761 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1762 return countMCSymbolRefExpr(BExpr->getLHS()) +
1763 countMCSymbolRefExpr(BExpr->getRHS());
1764
1765 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1766 return countMCSymbolRefExpr(UExpr->getSubExpr());
1767
1768 return 0;
1769}
1770
Jack Carter9e65aa32013-03-22 00:05:30 +00001771bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001772 MCStreamer &Out,
1773 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001774 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001775 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001776 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001777
Jack Carter9e65aa32013-03-22 00:05:30 +00001778 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001779
1780 if (MCID.isBranch() || MCID.isCall()) {
1781 const unsigned Opcode = Inst.getOpcode();
1782 MCOperand Offset;
1783
1784 switch (Opcode) {
1785 default:
1786 break;
Kai Nackee0245392015-01-27 19:11:28 +00001787 case Mips::BBIT0:
1788 case Mips::BBIT032:
1789 case Mips::BBIT1:
1790 case Mips::BBIT132:
1791 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001792 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001793
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001794 case Mips::BEQ:
1795 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001796 case Mips::BEQ_MM:
1797 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001798 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001799 Offset = Inst.getOperand(2);
1800 if (!Offset.isImm())
1801 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001802 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001803 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001804 if (OffsetToAlignment(Offset.getImm(),
1805 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001806 return Error(IDLoc, "branch to misaligned address");
1807 break;
1808 case Mips::BGEZ:
1809 case Mips::BGTZ:
1810 case Mips::BLEZ:
1811 case Mips::BLTZ:
1812 case Mips::BGEZAL:
1813 case Mips::BLTZAL:
1814 case Mips::BC1F:
1815 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001816 case Mips::BGEZ_MM:
1817 case Mips::BGTZ_MM:
1818 case Mips::BLEZ_MM:
1819 case Mips::BLTZ_MM:
1820 case Mips::BGEZAL_MM:
1821 case Mips::BLTZAL_MM:
1822 case Mips::BC1F_MM:
1823 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001824 case Mips::BC1EQZC_MMR6:
1825 case Mips::BC1NEZC_MMR6:
1826 case Mips::BC2EQZC_MMR6:
1827 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001828 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001829 Offset = Inst.getOperand(1);
1830 if (!Offset.isImm())
1831 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001832 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001833 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001834 if (OffsetToAlignment(Offset.getImm(),
1835 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001836 return Error(IDLoc, "branch to misaligned address");
1837 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001838 case Mips::BGEC: case Mips::BGEC_MMR6:
1839 case Mips::BLTC: case Mips::BLTC_MMR6:
1840 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1841 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1842 case Mips::BEQC: case Mips::BEQC_MMR6:
1843 case Mips::BNEC: case Mips::BNEC_MMR6:
1844 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1845 Offset = Inst.getOperand(2);
1846 if (!Offset.isImm())
1847 break; // We'll deal with this situation later on when applying fixups.
1848 if (!isIntN(18, Offset.getImm()))
1849 return Error(IDLoc, "branch target out of range");
1850 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1851 return Error(IDLoc, "branch to misaligned address");
1852 break;
1853 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1854 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1855 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1856 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1857 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1858 Offset = Inst.getOperand(1);
1859 if (!Offset.isImm())
1860 break; // We'll deal with this situation later on when applying fixups.
1861 if (!isIntN(18, Offset.getImm()))
1862 return Error(IDLoc, "branch target out of range");
1863 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1864 return Error(IDLoc, "branch to misaligned address");
1865 break;
1866 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1867 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1868 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1869 Offset = Inst.getOperand(1);
1870 if (!Offset.isImm())
1871 break; // We'll deal with this situation later on when applying fixups.
1872 if (!isIntN(23, Offset.getImm()))
1873 return Error(IDLoc, "branch target out of range");
1874 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1875 return Error(IDLoc, "branch to misaligned address");
1876 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001877 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001878 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001879 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001880 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001881 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1882 Offset = Inst.getOperand(1);
1883 if (!Offset.isImm())
1884 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001885 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001886 return Error(IDLoc, "branch target out of range");
1887 if (OffsetToAlignment(Offset.getImm(), 2LL))
1888 return Error(IDLoc, "branch to misaligned address");
1889 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001890 }
1891 }
1892
Daniel Sandersa84989a2014-06-16 13:25:35 +00001893 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1894 // We still accept it but it is a normal nop.
1895 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1896 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1897 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1898 "nop instruction");
1899 }
1900
Kai Nackee0245392015-01-27 19:11:28 +00001901 if (hasCnMips()) {
1902 const unsigned Opcode = Inst.getOpcode();
1903 MCOperand Opnd;
1904 int Imm;
1905
1906 switch (Opcode) {
1907 default:
1908 break;
1909
1910 case Mips::BBIT0:
1911 case Mips::BBIT032:
1912 case Mips::BBIT1:
1913 case Mips::BBIT132:
1914 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1915 // The offset is handled above
1916 Opnd = Inst.getOperand(1);
1917 if (!Opnd.isImm())
1918 return Error(IDLoc, "expected immediate operand kind");
1919 Imm = Opnd.getImm();
1920 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1921 Opcode == Mips::BBIT1 ? 63 : 31))
1922 return Error(IDLoc, "immediate operand value out of range");
1923 if (Imm > 31) {
1924 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1925 : Mips::BBIT132);
1926 Inst.getOperand(1).setImm(Imm - 32);
1927 }
1928 break;
1929
Kai Nackee0245392015-01-27 19:11:28 +00001930 case Mips::SEQi:
1931 case Mips::SNEi:
1932 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1933 Opnd = Inst.getOperand(2);
1934 if (!Opnd.isImm())
1935 return Error(IDLoc, "expected immediate operand kind");
1936 Imm = Opnd.getImm();
1937 if (!isInt<10>(Imm))
1938 return Error(IDLoc, "immediate operand value out of range");
1939 break;
1940 }
1941 }
1942
Simon Dardis509da1a2017-02-13 16:06:48 +00001943 // Warn on division by zero. We're checking here as all instructions get
1944 // processed here, not just the macros that need expansion.
1945 //
1946 // The MIPS backend models most of the divison instructions and macros as
1947 // three operand instructions. The pre-R6 divide instructions however have
1948 // two operands and explicitly define HI/LO as part of the instruction,
1949 // not in the operands.
1950 unsigned FirstOp = 1;
1951 unsigned SecondOp = 2;
1952 switch (Inst.getOpcode()) {
1953 default:
1954 break;
1955 case Mips::SDivIMacro:
1956 case Mips::UDivIMacro:
1957 case Mips::DSDivIMacro:
1958 case Mips::DUDivIMacro:
1959 if (Inst.getOperand(2).getImm() == 0) {
1960 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1961 Inst.getOperand(1).getReg() == Mips::ZERO_64)
1962 Warning(IDLoc, "dividing zero by zero");
1963 else
1964 Warning(IDLoc, "division by zero");
1965 }
1966 break;
1967 case Mips::DSDIV:
1968 case Mips::SDIV:
1969 case Mips::UDIV:
1970 case Mips::DUDIV:
1971 case Mips::UDIV_MM:
1972 case Mips::SDIV_MM:
1973 FirstOp = 0;
1974 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00001975 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00001976 case Mips::SDivMacro:
1977 case Mips::DSDivMacro:
1978 case Mips::UDivMacro:
1979 case Mips::DUDivMacro:
1980 case Mips::DIV:
1981 case Mips::DIVU:
1982 case Mips::DDIV:
1983 case Mips::DDIVU:
1984 case Mips::DIVU_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00001985 case Mips::DIV_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00001986 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
1987 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
1988 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
1989 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
1990 Warning(IDLoc, "dividing zero by zero");
1991 else
1992 Warning(IDLoc, "division by zero");
1993 }
1994 break;
1995 }
1996
Simon Atanasyan50485142016-12-12 17:40:26 +00001997 // For PIC code convert unconditional jump to unconditional branch.
1998 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
1999 inPicMode()) {
2000 MCInst BInst;
2001 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
2002 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2003 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2004 BInst.addOperand(Inst.getOperand(0));
2005 Inst = BInst;
2006 }
2007
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002008 // This expansion is not in a function called by tryExpandInstruction()
2009 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002010 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2011 inPicMode()) {
2012 warnIfNoMacro(IDLoc);
2013
2014 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2015
2016 // We can do this expansion if there's only 1 symbol in the argument
2017 // expression.
2018 if (countMCSymbolRefExpr(JalExpr) > 1)
2019 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2020
2021 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002022 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002023 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2024
2025 // FIXME: Add support for label+offset operands (currently causes an error).
2026 // FIXME: Add support for forward-declared local symbols.
2027 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002028 if (JalSym->isInSection() || JalSym->isTemporary() ||
Simon Atanasyan478220f2018-05-24 07:36:00 +00002029 (JalSym->isELF() &&
2030 cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002031 if (isABI_O32()) {
2032 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002033 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002034 // R_(MICRO)MIPS_GOT16 label
2035 // addiu $25, $25, 0
2036 // R_(MICRO)MIPS_LO16 label
2037 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002038 const MCExpr *Got16RelocExpr =
2039 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2040 const MCExpr *Lo16RelocExpr =
2041 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002042
Daniel Sandersa736b372016-04-29 13:33:12 +00002043 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2044 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2045 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2046 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002047 } else if (isABI_N32() || isABI_N64()) {
2048 // If it's a local symbol and the N32/N64 ABIs are being used,
2049 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002050 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002051 // R_(MICRO)MIPS_GOT_DISP label
2052 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002053 const MCExpr *GotDispRelocExpr =
2054 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002055
Daniel Sandersa736b372016-04-29 13:33:12 +00002056 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2057 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2058 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002059 }
2060 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002061 // If it's an external/weak symbol, we expand to:
2062 // lw/ld $25, 0($gp)
2063 // R_(MICRO)MIPS_CALL16 label
2064 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002065 const MCExpr *Call16RelocExpr =
2066 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002067
Daniel Sandersa736b372016-04-29 13:33:12 +00002068 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2069 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002070 }
2071
2072 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002073 if (IsCpRestoreSet && inMicroMipsMode())
2074 JalrInst.setOpcode(Mips::JALRS_MM);
2075 else
2076 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002077 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2078 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2079
Vladimir Stefanovic4433f932018-12-10 15:07:36 +00002080 if (EmitJalrReloc) {
2081 // As an optimization hint for the linker, before the JALR we add:
2082 // .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol
2083 // tmplabel:
2084 MCSymbol *TmpLabel = getContext().createTempSymbol();
2085 const MCExpr *TmpExpr = MCSymbolRefExpr::create(TmpLabel, getContext());
2086 const MCExpr *RelocJalrExpr =
2087 MCSymbolRefExpr::create(JalSym, MCSymbolRefExpr::VK_None,
2088 getContext(), IDLoc);
2089
2090 TOut.getStreamer().EmitRelocDirective(*TmpExpr,
2091 inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",
2092 RelocJalrExpr, IDLoc, *STI);
2093 TOut.getStreamer().EmitLabel(TmpLabel);
2094 }
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002095
2096 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002097 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002098 }
2099
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002100 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2101 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002102 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002103 // reference or immediate we may have to expand instructions.
2104 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002105 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002106 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2107 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002108 MCOperand &Op = Inst.getOperand(i);
2109 if (Op.isImm()) {
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00002110 int64_t MemOffset = Op.getImm();
Jack Carter9e65aa32013-03-22 00:05:30 +00002111 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002112 // Offset can't exceed 16bit value.
Simon Atanasyana1882672018-05-24 07:36:11 +00002113 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
Nirav Dave2364748a2016-09-16 18:30:20 +00002114 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002115 }
2116 } else if (Op.isExpr()) {
2117 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002118 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002119 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002120 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002121 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002122 // Expand symbol.
Simon Atanasyana1882672018-05-24 07:36:11 +00002123 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
Nirav Dave2364748a2016-09-16 18:30:20 +00002124 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002125 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002126 } else if (!isEvaluated(Expr)) {
Simon Atanasyana1882672018-05-24 07:36:11 +00002127 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
Nirav Dave2364748a2016-09-16 18:30:20 +00002128 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002129 }
2130 }
2131 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002132 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002133 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002134
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002135 if (inMicroMipsMode()) {
Simon Dardis6a319922018-05-25 16:15:48 +00002136 if (MCID.mayLoad() && Inst.getOpcode() != Mips::LWP_MM) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002137 // Try to create 16-bit GP relative load instruction.
2138 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2139 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2140 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2141 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2142 MCOperand &Op = Inst.getOperand(i);
2143 if (Op.isImm()) {
2144 int MemOffset = Op.getImm();
2145 MCOperand &DstReg = Inst.getOperand(0);
2146 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002147 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002148 getContext().getRegisterInfo()->getRegClass(
2149 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002150 (BaseReg.getReg() == Mips::GP ||
2151 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002152
Daniel Sandersa736b372016-04-29 13:33:12 +00002153 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2154 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002155 return false;
2156 }
2157 }
2158 }
2159 } // for
2160 } // if load
2161
2162 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2163
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002164 MCOperand Opnd;
2165 int Imm;
2166
2167 switch (Inst.getOpcode()) {
2168 default:
2169 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002170 case Mips::ADDIUSP_MM:
2171 Opnd = Inst.getOperand(0);
2172 if (!Opnd.isImm())
2173 return Error(IDLoc, "expected immediate operand kind");
2174 Imm = Opnd.getImm();
2175 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2176 Imm % 4 != 0)
2177 return Error(IDLoc, "immediate operand value out of range");
2178 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002179 case Mips::SLL16_MM:
2180 case Mips::SRL16_MM:
2181 Opnd = Inst.getOperand(2);
2182 if (!Opnd.isImm())
2183 return Error(IDLoc, "expected immediate operand kind");
2184 Imm = Opnd.getImm();
2185 if (Imm < 1 || Imm > 8)
2186 return Error(IDLoc, "immediate operand value out of range");
2187 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002188 case Mips::LI16_MM:
2189 Opnd = Inst.getOperand(1);
2190 if (!Opnd.isImm())
2191 return Error(IDLoc, "expected immediate operand kind");
2192 Imm = Opnd.getImm();
2193 if (Imm < -1 || Imm > 126)
2194 return Error(IDLoc, "immediate operand value out of range");
2195 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002196 case Mips::ADDIUR2_MM:
2197 Opnd = Inst.getOperand(2);
2198 if (!Opnd.isImm())
2199 return Error(IDLoc, "expected immediate operand kind");
2200 Imm = Opnd.getImm();
2201 if (!(Imm == 1 || Imm == -1 ||
2202 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2203 return Error(IDLoc, "immediate operand value out of range");
2204 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002205 case Mips::ANDI16_MM:
2206 Opnd = Inst.getOperand(2);
2207 if (!Opnd.isImm())
2208 return Error(IDLoc, "expected immediate operand kind");
2209 Imm = Opnd.getImm();
2210 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2211 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2212 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2213 return Error(IDLoc, "immediate operand value out of range");
2214 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002215 case Mips::LBU16_MM:
2216 Opnd = Inst.getOperand(2);
2217 if (!Opnd.isImm())
2218 return Error(IDLoc, "expected immediate operand kind");
2219 Imm = Opnd.getImm();
2220 if (Imm < -1 || Imm > 14)
2221 return Error(IDLoc, "immediate operand value out of range");
2222 break;
2223 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002224 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002225 Opnd = Inst.getOperand(2);
2226 if (!Opnd.isImm())
2227 return Error(IDLoc, "expected immediate operand kind");
2228 Imm = Opnd.getImm();
2229 if (Imm < 0 || Imm > 15)
2230 return Error(IDLoc, "immediate operand value out of range");
2231 break;
2232 case Mips::LHU16_MM:
2233 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002234 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002235 Opnd = Inst.getOperand(2);
2236 if (!Opnd.isImm())
2237 return Error(IDLoc, "expected immediate operand kind");
2238 Imm = Opnd.getImm();
2239 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2240 return Error(IDLoc, "immediate operand value out of range");
2241 break;
2242 case Mips::LW16_MM:
2243 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002244 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002245 Opnd = Inst.getOperand(2);
2246 if (!Opnd.isImm())
2247 return Error(IDLoc, "expected immediate operand kind");
2248 Imm = Opnd.getImm();
2249 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2250 return Error(IDLoc, "immediate operand value out of range");
2251 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002252 case Mips::ADDIUPC_MM:
Simon Dardis6a319922018-05-25 16:15:48 +00002253 Opnd = Inst.getOperand(1);
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002254 if (!Opnd.isImm())
2255 return Error(IDLoc, "expected immediate operand kind");
Simon Dardis6a319922018-05-25 16:15:48 +00002256 Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002257 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002258 return Error(IDLoc, "immediate operand value out of range");
2259 break;
Simon Dardis6a319922018-05-25 16:15:48 +00002260 case Mips::LWP_MM:
2261 case Mips::SWP_MM:
2262 if (Inst.getOperand(0).getReg() == Mips::RA)
2263 return Error(IDLoc, "invalid operand for instruction");
2264 break;
Simon Atanasyan852dd832018-09-19 18:46:21 +00002265 case Mips::MOVEP_MM:
2266 case Mips::MOVEP_MMR6: {
2267 unsigned R0 = Inst.getOperand(0).getReg();
2268 unsigned R1 = Inst.getOperand(1).getReg();
2269 bool RegPair = ((R0 == Mips::A1 && R1 == Mips::A2) ||
2270 (R0 == Mips::A1 && R1 == Mips::A3) ||
2271 (R0 == Mips::A2 && R1 == Mips::A3) ||
2272 (R0 == Mips::A0 && R1 == Mips::S5) ||
2273 (R0 == Mips::A0 && R1 == Mips::S6) ||
2274 (R0 == Mips::A0 && R1 == Mips::A1) ||
2275 (R0 == Mips::A0 && R1 == Mips::A2) ||
2276 (R0 == Mips::A0 && R1 == Mips::A3));
2277 if (!RegPair)
2278 return Error(IDLoc, "invalid operand for instruction");
2279 break;
2280 }
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002281 }
2282 }
2283
Daniel Sandersd8c07762016-04-18 12:35:36 +00002284 bool FillDelaySlot =
2285 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2286 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002287 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002288
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002289 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002290 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002291 switch (ExpandResult) {
2292 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002293 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002294 break;
2295 case MER_Success:
2296 break;
2297 case MER_Fail:
2298 return true;
2299 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002300
Daniel Sanderscda908a2016-05-16 09:10:13 +00002301 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2302 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002303 if (inMicroMipsMode()) {
Daniel Sanderscda908a2016-05-16 09:10:13 +00002304 TOut.setUsesMicroMips();
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002305 TOut.updateABIInfo(*this);
2306 }
Daniel Sanderscda908a2016-05-16 09:10:13 +00002307
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002308 // If this instruction has a delay slot and .set reorder is active,
2309 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002310 if (FillDelaySlot) {
Aleksandar Beserminji8abf6802019-01-09 15:58:02 +00002311 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00002312 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002313 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002314
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002315 if ((Inst.getOpcode() == Mips::JalOneReg ||
2316 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2317 isPicAndNotNxxAbi()) {
2318 if (IsCpRestoreSet) {
2319 // We need a NOP between the JALR and the LW:
2320 // If .set reorder has been used, we've already emitted a NOP.
2321 // If .set noreorder has been used, we need to emit a NOP at this point.
2322 if (!AssemblerOptions.back()->isReorder())
Aleksandar Beserminji8abf6802019-01-09 15:58:02 +00002323 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc,
Daniel Sandersa736b372016-04-29 13:33:12 +00002324 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002325
2326 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002327 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002328 } else
2329 Warning(IDLoc, "no .cprestore used in PIC mode");
2330 }
2331
Jack Carter9e65aa32013-03-22 00:05:30 +00002332 return false;
2333}
2334
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002335MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002336MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2337 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002338 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002339 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002340 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002341 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002342 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002343 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002344 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002345 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002346 case Mips::LoadAddrImm64:
2347 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2348 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2349 "expected immediate operand kind");
2350
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002351 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2352 Inst.getOperand(1),
2353 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002354 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002355 ? MER_Fail
2356 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002357 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002358 case Mips::LoadAddrReg64:
2359 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2360 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2361 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2362 "expected immediate operand kind");
2363
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002364 return expandLoadAddress(Inst.getOperand(0).getReg(),
2365 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2366 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002367 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002368 ? MER_Fail
2369 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002370 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002371 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002372 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2373 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002374 case Mips::SWM_MM:
2375 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002376 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2377 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002378 case Mips::JalOneReg:
2379 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002380 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002381 case Mips::BneImm:
2382 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002383 case Mips::BEQLImmMacro:
2384 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002385 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002386 case Mips::BLT:
2387 case Mips::BLE:
2388 case Mips::BGE:
2389 case Mips::BGT:
2390 case Mips::BLTU:
2391 case Mips::BLEU:
2392 case Mips::BGEU:
2393 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002394 case Mips::BLTL:
2395 case Mips::BLEL:
2396 case Mips::BGEL:
2397 case Mips::BGTL:
2398 case Mips::BLTUL:
2399 case Mips::BLEUL:
2400 case Mips::BGEUL:
2401 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002402 case Mips::BLTImmMacro:
2403 case Mips::BLEImmMacro:
2404 case Mips::BGEImmMacro:
2405 case Mips::BGTImmMacro:
2406 case Mips::BLTUImmMacro:
2407 case Mips::BLEUImmMacro:
2408 case Mips::BGEUImmMacro:
2409 case Mips::BGTUImmMacro:
2410 case Mips::BLTLImmMacro:
2411 case Mips::BLELImmMacro:
2412 case Mips::BGELImmMacro:
2413 case Mips::BGTLImmMacro:
2414 case Mips::BLTULImmMacro:
2415 case Mips::BLEULImmMacro:
2416 case Mips::BGEULImmMacro:
2417 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002418 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002419 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002420 case Mips::SDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002421 case Mips::SRemMacro:
2422 case Mips::SRemIMacro:
2423 return expandDivRem(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2424 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002425 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002426 case Mips::DSDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002427 case Mips::DSRemMacro:
2428 case Mips::DSRemIMacro:
2429 return expandDivRem(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2430 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002431 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002432 case Mips::UDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002433 case Mips::URemMacro:
2434 case Mips::URemIMacro:
2435 return expandDivRem(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2436 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002437 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002438 case Mips::DUDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002439 case Mips::DURemMacro:
2440 case Mips::DURemIMacro:
2441 return expandDivRem(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2442 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002443 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002444 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2445 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002446 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002447 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002448 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002449 case Mips::PseudoTRUNC_W_D:
2450 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2451 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002452
2453 case Mips::LoadImmSingleGPR:
2454 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2455 ? MER_Fail
2456 : MER_Success;
2457 case Mips::LoadImmSingleFGR:
2458 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2459 ? MER_Fail
2460 : MER_Success;
2461 case Mips::LoadImmDoubleGPR:
2462 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2463 ? MER_Fail
2464 : MER_Success;
2465 case Mips::LoadImmDoubleFGR:
2466 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2467 ? MER_Fail
2468 : MER_Success;
2469 case Mips::LoadImmDoubleFGR_32:
2470 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2471 ? MER_Fail
2472 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002473 case Mips::Ulh:
2474 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2475 case Mips::Ulhu:
2476 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002477 case Mips::Ush:
2478 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002479 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002480 case Mips::Usw:
2481 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002482 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002483 case Mips::NORImm64:
2484 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2485 case Mips::SLTImm64:
2486 if (isInt<16>(Inst.getOperand(2).getImm())) {
2487 Inst.setOpcode(Mips::SLTi64);
2488 return MER_NotAMacro;
2489 }
2490 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2491 case Mips::SLTUImm64:
2492 if (isInt<16>(Inst.getOperand(2).getImm())) {
2493 Inst.setOpcode(Mips::SLTiu64);
2494 return MER_NotAMacro;
2495 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002496 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002497 case Mips::ADDi: case Mips::ADDi_MM:
2498 case Mips::ADDiu: case Mips::ADDiu_MM:
2499 case Mips::SLTi: case Mips::SLTi_MM:
2500 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002501 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2502 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2503 int64_t ImmValue = Inst.getOperand(2).getImm();
2504 if (isInt<16>(ImmValue))
2505 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002506 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2507 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002508 }
2509 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002510 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2511 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2512 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
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 (isUInt<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;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002522 case Mips::ROL:
2523 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002524 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002525 case Mips::ROLImm:
2526 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002527 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002528 case Mips::DROL:
2529 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002530 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002531 case Mips::DROLImm:
2532 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002533 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002534 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002535 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002536 case Mips::MULImmMacro:
2537 case Mips::DMULImmMacro:
2538 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2539 case Mips::MULOMacro:
2540 case Mips::DMULOMacro:
2541 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2542 case Mips::MULOUMacro:
2543 case Mips::DMULOUMacro:
2544 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2545 case Mips::DMULMacro:
2546 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002547 case Mips::LDMacro:
2548 case Mips::SDMacro:
2549 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2550 Inst.getOpcode() == Mips::LDMacro)
2551 ? MER_Fail
2552 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002553 case Mips::SEQMacro:
2554 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2555 case Mips::SEQIMacro:
2556 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisde5ed0c2017-11-14 22:26:42 +00002557 case Mips::MFTC0: case Mips::MTTC0:
2558 case Mips::MFTGPR: case Mips::MTTGPR:
2559 case Mips::MFTLO: case Mips::MTTLO:
2560 case Mips::MFTHI: case Mips::MTTHI:
2561 case Mips::MFTACX: case Mips::MTTACX:
2562 case Mips::MFTDSP: case Mips::MTTDSP:
2563 case Mips::MFTC1: case Mips::MTTC1:
2564 case Mips::MFTHC1: case Mips::MTTHC1:
2565 case Mips::CFTC1: case Mips::CTTC1:
2566 return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002567 }
Jack Carter30a59822012-10-04 04:03:53 +00002568}
Jack Carter92995f12012-10-06 00:53:28 +00002569
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002570bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002571 MCStreamer &Out,
2572 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002573 MipsTargetStreamer &TOut = getTargetStreamer();
2574
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002575 // Create a JALR instruction which is going to replace the pseudo-JAL.
2576 MCInst JalrInst;
2577 JalrInst.setLoc(IDLoc);
2578 const MCOperand FirstRegOp = Inst.getOperand(0);
2579 const unsigned Opcode = Inst.getOpcode();
2580
2581 if (Opcode == Mips::JalOneReg) {
2582 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002583 if (IsCpRestoreSet && inMicroMipsMode()) {
2584 JalrInst.setOpcode(Mips::JALRS16_MM);
2585 JalrInst.addOperand(FirstRegOp);
2586 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002587 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002588 JalrInst.addOperand(FirstRegOp);
2589 } else {
2590 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002591 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002592 JalrInst.addOperand(FirstRegOp);
2593 }
2594 } else if (Opcode == Mips::JalTwoReg) {
2595 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002596 if (IsCpRestoreSet && inMicroMipsMode())
2597 JalrInst.setOpcode(Mips::JALRS_MM);
2598 else
2599 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002600 JalrInst.addOperand(FirstRegOp);
2601 const MCOperand SecondRegOp = Inst.getOperand(1);
2602 JalrInst.addOperand(SecondRegOp);
2603 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002604 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002605
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002606 // If .set reorder is active and branch instruction has a delay slot,
2607 // emit a NOP after it.
2608 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002609 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Aleksandar Beserminji8abf6802019-01-09 15:58:02 +00002610 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst), IDLoc,
Daniel Sandersa736b372016-04-29 13:33:12 +00002611 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002612
2613 return false;
2614}
2615
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002616/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002617template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002618 unsigned BitNum = findFirstSet(x);
2619
2620 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2621}
2622
2623/// Load (or add) an immediate into a register.
2624///
2625/// @param ImmValue The immediate to load.
2626/// @param DstReg The register that will hold the immediate.
2627/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2628/// for a simple initialization.
2629/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2630/// @param IsAddress True if the immediate represents an address. False if it
2631/// is an integer.
2632/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002633bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002634 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002635 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2636 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002637 MipsTargetStreamer &TOut = getTargetStreamer();
2638
Toma Tabacu00e98672015-05-01 12:19:27 +00002639 if (!Is32BitImm && !isGP64bit()) {
2640 Error(IDLoc, "instruction requires a 64-bit architecture");
2641 return true;
2642 }
2643
Daniel Sanders03f9c012015-07-14 12:24:22 +00002644 if (Is32BitImm) {
2645 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2646 // Sign extend up to 64-bit so that the predicates match the hardware
2647 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2648 // true.
2649 ImmValue = SignExtend64<32>(ImmValue);
2650 } else {
2651 Error(IDLoc, "instruction requires a 32-bit immediate");
2652 return true;
2653 }
2654 }
2655
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002656 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2657 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2658
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002659 bool UseSrcReg = false;
2660 if (SrcReg != Mips::NoRegister)
2661 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002662
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002663 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002664 if (UseSrcReg &&
2665 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002666 // At this point we need AT to perform the expansions and we exit if it is
2667 // not available.
2668 unsigned ATReg = getATReg(IDLoc);
2669 if (!ATReg)
2670 return true;
2671 TmpReg = ATReg;
2672 }
2673
Daniel Sanders03f9c012015-07-14 12:24:22 +00002674 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002675 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002676 SrcReg = ZeroReg;
2677
2678 // This doesn't quite follow the usual ABI expectations for N32 but matches
2679 // traditional assembler behaviour. N32 would normally use addiu for both
2680 // integers and addresses.
2681 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002682 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002683 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002684 }
2685
Daniel Sandersa736b372016-04-29 13:33:12 +00002686 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002687 return false;
2688 }
2689
2690 if (isUInt<16>(ImmValue)) {
2691 unsigned TmpReg = DstReg;
2692 if (SrcReg == DstReg) {
2693 TmpReg = getATReg(IDLoc);
2694 if (!TmpReg)
2695 return true;
2696 }
2697
Daniel Sandersa736b372016-04-29 13:33:12 +00002698 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002699 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002700 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002701 return false;
2702 }
2703
2704 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002705 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002706
Toma Tabacu79588102015-04-29 10:19:56 +00002707 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2708 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002709 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002710 // Traditional behaviour seems to special case this particular value. It's
2711 // not clear why other masks are handled differently.
2712 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002713 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2714 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002715 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002716 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002717 return false;
2718 }
2719
2720 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002721 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002722 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2723 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002724 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002725 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002726 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002727 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002728 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002729 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002730
Daniel Sandersa736b372016-04-29 13:33:12 +00002731 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002732 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002733 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002734 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002735 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002736 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002737 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002738
2739 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2740 if (Is32BitImm) {
2741 Error(IDLoc, "instruction requires a 32-bit immediate");
2742 return true;
2743 }
2744
2745 // Traditionally, these immediates are shifted as little as possible and as
2746 // such we align the most significant bit to bit 15 of our temporary.
2747 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2748 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2749 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2750 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002751 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2752 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002753
2754 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002755 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002756
2757 return false;
2758 }
2759
2760 warnIfNoMacro(IDLoc);
2761
2762 // The remaining case is packed with a sequence of dsll and ori with zeros
2763 // being omitted and any neighbouring dsll's being coalesced.
2764 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2765
2766 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2767 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002768 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002769 return false;
2770
2771 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2772 // skip it and defer the shift to the next chunk.
2773 unsigned ShiftCarriedForwards = 16;
2774 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2775 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2776
2777 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002778 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2779 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002780 ShiftCarriedForwards = 0;
2781 }
2782
2783 ShiftCarriedForwards += 16;
2784 }
2785 ShiftCarriedForwards -= 16;
2786
2787 // Finish any remaining shifts left by trailing zeros.
2788 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002789 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002790
2791 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002792 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002793
Matheus Almeida3813d572014-06-19 14:39:14 +00002794 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002795}
Jack Carter92995f12012-10-06 00:53:28 +00002796
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002797bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002798 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002799 const MCOperand &ImmOp = Inst.getOperand(1);
2800 assert(ImmOp.isImm() && "expected immediate operand kind");
2801 const MCOperand &DstRegOp = Inst.getOperand(0);
2802 assert(DstRegOp.isReg() && "expected register operand kind");
2803
2804 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002805 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002806 return true;
2807
2808 return false;
2809}
2810
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002811bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2812 const MCOperand &Offset,
2813 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002814 MCStreamer &Out,
2815 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002816 // la can't produce a usable address when addresses are 64-bit.
2817 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2818 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2819 // We currently can't do this because we depend on the equality
2820 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2821 Error(IDLoc, "la used to load 64-bit address");
2822 // Continue as if we had 'dla' instead.
2823 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002824 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002825 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002826
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002827 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002828 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002829 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002830 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002831 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002832
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002833 if (!Offset.isImm())
2834 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002835 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002836
Scott Egerton24557012016-01-21 15:11:01 +00002837 if (!ABI.ArePtrs64bit()) {
2838 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2839 Is32BitAddress = true;
2840 }
2841
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002842 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002843 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002844}
2845
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002846bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2847 unsigned DstReg, unsigned SrcReg,
2848 bool Is32BitSym, SMLoc IDLoc,
2849 MCStreamer &Out,
2850 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002851 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002852 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002853 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002854 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002855
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002856 if (inPicMode() && ABI.IsO32()) {
2857 MCValue Res;
2858 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2859 Error(IDLoc, "expected relocatable expression");
2860 return true;
2861 }
2862 if (Res.getSymB() != nullptr) {
2863 Error(IDLoc, "expected relocatable expression with only one symbol");
2864 return true;
2865 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002866
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002867 // The case where the result register is $25 is somewhat special. If the
2868 // symbol in the final relocation is external and not modified with a
2869 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2870 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002871 Res.getConstant() == 0 &&
2872 !(Res.getSymA()->getSymbol().isInSection() ||
2873 Res.getSymA()->getSymbol().isTemporary() ||
2874 (Res.getSymA()->getSymbol().isELF() &&
2875 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2876 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002877 const MCExpr *CallExpr =
2878 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2879 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2880 MCOperand::createExpr(CallExpr), IDLoc, STI);
2881 return false;
2882 }
2883
2884 // The remaining cases are:
2885 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2886 // >addiu $tmp, $tmp, %lo(offset)
2887 // >addiu $rd, $tmp, $rs
2888 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2889 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2890 // >addiu $rd, $tmp, $rs
2891 // The addiu's marked with a '>' may be omitted if they are redundant. If
2892 // this happens then the last instruction must use $rd as the result
2893 // register.
2894 const MipsMCExpr *GotExpr =
2895 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2896 const MCExpr *LoExpr = nullptr;
2897 if (Res.getSymA()->getSymbol().isInSection() ||
2898 Res.getSymA()->getSymbol().isTemporary())
2899 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2900 else if (Res.getConstant() != 0) {
2901 // External symbols fully resolve the symbol with just the %got(symbol)
2902 // but we must still account for any offset to the symbol for expressions
2903 // like symbol+8.
2904 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2905 }
2906
2907 unsigned TmpReg = DstReg;
2908 if (UseSrcReg &&
2909 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2910 SrcReg)) {
2911 // If $rs is the same as $rd, we need to use AT.
2912 // If it is not available we exit.
2913 unsigned ATReg = getATReg(IDLoc);
2914 if (!ATReg)
2915 return true;
2916 TmpReg = ATReg;
2917 }
2918
2919 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2920 MCOperand::createExpr(GotExpr), IDLoc, STI);
2921
2922 if (LoExpr)
2923 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2924 IDLoc, STI);
2925
2926 if (UseSrcReg)
2927 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2928
2929 return false;
2930 }
2931
Simon Dardisda96c432017-06-30 15:44:27 +00002932 if (inPicMode() && ABI.ArePtrs64bit()) {
2933 MCValue Res;
2934 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2935 Error(IDLoc, "expected relocatable expression");
2936 return true;
2937 }
2938 if (Res.getSymB() != nullptr) {
2939 Error(IDLoc, "expected relocatable expression with only one symbol");
2940 return true;
2941 }
2942
2943 // The case where the result register is $25 is somewhat special. If the
2944 // symbol in the final relocation is external and not modified with a
2945 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2946 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2947 Res.getConstant() == 0 &&
2948 !(Res.getSymA()->getSymbol().isInSection() ||
2949 Res.getSymA()->getSymbol().isTemporary() ||
2950 (Res.getSymA()->getSymbol().isELF() &&
2951 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2952 ELF::STB_LOCAL))) {
2953 const MCExpr *CallExpr =
2954 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2955 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2956 MCOperand::createExpr(CallExpr), IDLoc, STI);
2957 return false;
2958 }
2959
2960 // The remaining cases are:
2961 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2962 // >daddiu $tmp, $tmp, offset
2963 // >daddu $rd, $tmp, $rs
2964 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2965 // this happens then the last instruction must use $rd as the result
2966 // register.
2967 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2968 Res.getSymA(),
2969 getContext());
2970 const MCExpr *LoExpr = nullptr;
2971 if (Res.getConstant() != 0) {
2972 // Symbols fully resolve with just the %got_disp(symbol) but we
2973 // must still account for any offset to the symbol for
2974 // expressions like symbol+8.
2975 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2976
2977 // FIXME: Offsets greater than 16 bits are not yet implemented.
2978 // FIXME: The correct range is a 32-bit sign-extended number.
2979 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2980 Error(IDLoc, "macro instruction uses large offset, which is not "
2981 "currently supported");
2982 return true;
2983 }
2984 }
2985
2986 unsigned TmpReg = DstReg;
2987 if (UseSrcReg &&
2988 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2989 SrcReg)) {
2990 // If $rs is the same as $rd, we need to use AT.
2991 // If it is not available we exit.
2992 unsigned ATReg = getATReg(IDLoc);
2993 if (!ATReg)
2994 return true;
2995 TmpReg = ATReg;
2996 }
2997
2998 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
2999 MCOperand::createExpr(GotExpr), IDLoc, STI);
3000
3001 if (LoExpr)
3002 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3003 IDLoc, STI);
3004
3005 if (UseSrcReg)
3006 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
3007
3008 return false;
3009 }
3010
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003011 const MipsMCExpr *HiExpr =
3012 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
3013 const MipsMCExpr *LoExpr =
3014 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00003015
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003016 // This is the 64-bit symbol address expansion.
3017 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00003018 // We need AT for the 64-bit expansion in the cases where the optional
3019 // source register is the destination register and for the superscalar
3020 // scheduled form.
3021 //
3022 // If it is not available we exit if the destination is the same as the
3023 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003024
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003025 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003026 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003027 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003028 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003029
Simon Dardis3aa8a902017-02-06 12:43:46 +00003030 bool RdRegIsRsReg =
3031 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
3032
3033 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
3034 unsigned ATReg = getATReg(IDLoc);
3035
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003036 // If $rs is the same as $rd:
3037 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
3038 // daddiu $at, $at, %higher(sym)
3039 // dsll $at, $at, 16
3040 // daddiu $at, $at, %hi(sym)
3041 // dsll $at, $at, 16
3042 // daddiu $at, $at, %lo(sym)
3043 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00003044 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3045 STI);
3046 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3047 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3048 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3049 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3050 IDLoc, STI);
3051 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3052 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3053 IDLoc, STI);
3054 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003055
3056 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00003057 } else if (canUseATReg() && !RdRegIsRsReg) {
3058 unsigned ATReg = getATReg(IDLoc);
3059
3060 // If the $rs is different from $rd or if $rs isn't specified and we
3061 // have $at available:
3062 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3063 // lui $at, %hi(sym)
3064 // daddiu $rd, $rd, %higher(sym)
3065 // daddiu $at, $at, %lo(sym)
3066 // dsll32 $rd, $rd, 0
3067 // daddu $rd, $rd, $at
3068 // (daddu $rd, $rd, $rs)
3069 //
3070 // Which is preferred for superscalar issue.
3071 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3072 STI);
3073 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3074 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3075 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3076 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3077 IDLoc, STI);
3078 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3079 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3080 if (UseSrcReg)
3081 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3082
3083 return false;
3084 } else if (!canUseATReg() && !RdRegIsRsReg) {
3085 // Otherwise, synthesize the address in the destination register
3086 // serially:
3087 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3088 // daddiu $rd, $rd, %higher(sym)
3089 // dsll $rd, $rd, 16
3090 // daddiu $rd, $rd, %hi(sym)
3091 // dsll $rd, $rd, 16
3092 // daddiu $rd, $rd, %lo(sym)
3093 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3094 STI);
3095 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3096 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3097 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3098 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3099 MCOperand::createExpr(HiExpr), IDLoc, STI);
3100 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3101 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3102 MCOperand::createExpr(LoExpr), IDLoc, STI);
3103 if (UseSrcReg)
3104 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3105
3106 return false;
3107 } else {
3108 // We have a case where SrcReg == DstReg and we don't have $at
3109 // available. We can't expand this case, so error out appropriately.
3110 assert(SrcReg == DstReg && !canUseATReg() &&
3111 "Could have expanded dla but didn't?");
3112 reportParseError(IDLoc,
3113 "pseudo-instruction requires $at, which is not available");
3114 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003115 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003116 }
3117
3118 // And now, the 32-bit symbol address expansion:
3119 // If $rs is the same as $rd:
3120 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3121 // ori $at, $at, %lo(sym)
3122 // addu $rd, $at, $rd
3123 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3124 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3125 // ori $rd, $rd, %lo(sym)
3126 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003127 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003128 if (UseSrcReg &&
3129 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003130 // If $rs is the same as $rd, we need to use AT.
3131 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003132 unsigned ATReg = getATReg(IDLoc);
3133 if (!ATReg)
3134 return true;
3135 TmpReg = ATReg;
3136 }
3137
Daniel Sandersa736b372016-04-29 13:33:12 +00003138 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3139 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3140 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003141
Toma Tabacufb9d1252015-06-22 12:08:39 +00003142 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003143 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003144 else
Scott Egerton24557012016-01-21 15:11:01 +00003145 assert(
3146 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003147
Toma Tabacu674825c2015-06-16 12:16:24 +00003148 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003149}
3150
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003151// Each double-precision register DO-D15 overlaps with two of the single
3152// precision registers F0-F31. As an example, all of the following hold true:
3153// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3154static unsigned nextReg(unsigned Reg) {
3155 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3156 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3157 switch (Reg) {
3158 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3159 case Mips::ZERO: return Mips::AT;
3160 case Mips::AT: return Mips::V0;
3161 case Mips::V0: return Mips::V1;
3162 case Mips::V1: return Mips::A0;
3163 case Mips::A0: return Mips::A1;
3164 case Mips::A1: return Mips::A2;
3165 case Mips::A2: return Mips::A3;
3166 case Mips::A3: return Mips::T0;
3167 case Mips::T0: return Mips::T1;
3168 case Mips::T1: return Mips::T2;
3169 case Mips::T2: return Mips::T3;
3170 case Mips::T3: return Mips::T4;
3171 case Mips::T4: return Mips::T5;
3172 case Mips::T5: return Mips::T6;
3173 case Mips::T6: return Mips::T7;
3174 case Mips::T7: return Mips::S0;
3175 case Mips::S0: return Mips::S1;
3176 case Mips::S1: return Mips::S2;
3177 case Mips::S2: return Mips::S3;
3178 case Mips::S3: return Mips::S4;
3179 case Mips::S4: return Mips::S5;
3180 case Mips::S5: return Mips::S6;
3181 case Mips::S6: return Mips::S7;
3182 case Mips::S7: return Mips::T8;
3183 case Mips::T8: return Mips::T9;
3184 case Mips::T9: return Mips::K0;
3185 case Mips::K0: return Mips::K1;
3186 case Mips::K1: return Mips::GP;
3187 case Mips::GP: return Mips::SP;
3188 case Mips::SP: return Mips::FP;
3189 case Mips::FP: return Mips::RA;
3190 case Mips::RA: return Mips::ZERO;
3191 case Mips::D0: return Mips::F1;
3192 case Mips::D1: return Mips::F3;
3193 case Mips::D2: return Mips::F5;
3194 case Mips::D3: return Mips::F7;
3195 case Mips::D4: return Mips::F9;
3196 case Mips::D5: return Mips::F11;
3197 case Mips::D6: return Mips::F13;
3198 case Mips::D7: return Mips::F15;
3199 case Mips::D8: return Mips::F17;
3200 case Mips::D9: return Mips::F19;
3201 case Mips::D10: return Mips::F21;
3202 case Mips::D11: return Mips::F23;
3203 case Mips::D12: return Mips::F25;
3204 case Mips::D13: return Mips::F27;
3205 case Mips::D14: return Mips::F29;
3206 case Mips::D15: return Mips::F31;
3207 }
3208}
3209
3210// FIXME: This method is too general. In principle we should compute the number
3211// of instructions required to synthesize the immediate inline compared to
3212// synthesizing the address inline and relying on non .text sections.
3213// For static O32 and N32 this may yield a small benefit, for static N64 this is
3214// likely to yield a much larger benefit as we have to synthesize a 64bit
3215// address to load a 64 bit value.
3216bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3217 MCSymbol *Sym) {
3218 unsigned ATReg = getATReg(IDLoc);
3219 if (!ATReg)
3220 return true;
3221
3222 if(IsPicEnabled) {
3223 const MCExpr *GotSym =
3224 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3225 const MipsMCExpr *GotExpr =
3226 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3227
3228 if(isABI_O32() || isABI_N32()) {
3229 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3230 IDLoc, STI);
3231 } else { //isABI_N64()
3232 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3233 IDLoc, STI);
3234 }
3235 } else { //!IsPicEnabled
3236 const MCExpr *HiSym =
3237 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3238 const MipsMCExpr *HiExpr =
3239 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3240
3241 // FIXME: This is technically correct but gives a different result to gas,
3242 // but gas is incomplete there (it has a fixme noting it doesn't work with
3243 // 64-bit addresses).
3244 // FIXME: With -msym32 option, the address expansion for N64 should probably
3245 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3246 // symbol's value is considered sign extended.
3247 if(isABI_O32() || isABI_N32()) {
3248 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3249 } else { //isABI_N64()
3250 const MCExpr *HighestSym =
3251 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3252 const MipsMCExpr *HighestExpr =
3253 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3254 const MCExpr *HigherSym =
3255 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3256 const MipsMCExpr *HigherExpr =
3257 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3258
3259 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3260 STI);
3261 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3262 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3263 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3264 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3265 IDLoc, STI);
3266 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3267 }
3268 }
3269 return false;
3270}
3271
3272bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3273 bool Is64FPU, SMLoc IDLoc,
3274 MCStreamer &Out,
3275 const MCSubtargetInfo *STI) {
3276 MipsTargetStreamer &TOut = getTargetStreamer();
3277 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3278 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3279 "Invalid instruction operand.");
3280
3281 unsigned FirstReg = Inst.getOperand(0).getReg();
3282 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3283
3284 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3285 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3286 // exponent field), convert it to double (e.g. 1 to 1.0)
3287 if ((HiImmOp64 & 0x7ff00000) == 0) {
3288 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3289 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3290 }
3291
3292 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3293 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3294
3295 if (IsSingle) {
3296 // Conversion of a double in an uint64_t to a float in a uint32_t,
3297 // retaining the bit pattern of a float.
3298 uint32_t ImmOp32;
3299 double doubleImm = BitsToDouble(ImmOp64);
3300 float tmp_float = static_cast<float>(doubleImm);
3301 ImmOp32 = FloatToBits(tmp_float);
3302
3303 if (IsGPR) {
3304 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3305 Out, STI))
3306 return true;
3307 return false;
3308 } else {
3309 unsigned ATReg = getATReg(IDLoc);
3310 if (!ATReg)
3311 return true;
3312 if (LoImmOp64 == 0) {
3313 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3314 Out, STI))
3315 return true;
3316 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3317 return false;
3318 }
3319
3320 MCSection *CS = getStreamer().getCurrentSectionOnly();
3321 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3322 // where appropriate.
3323 MCSection *ReadOnlySection = getContext().getELFSection(
3324 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3325
3326 MCSymbol *Sym = getContext().createTempSymbol();
3327 const MCExpr *LoSym =
3328 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3329 const MipsMCExpr *LoExpr =
3330 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3331
3332 getStreamer().SwitchSection(ReadOnlySection);
3333 getStreamer().EmitLabel(Sym, IDLoc);
3334 getStreamer().EmitIntValue(ImmOp32, 4);
3335 getStreamer().SwitchSection(CS);
3336
3337 if(emitPartialAddress(TOut, IDLoc, Sym))
3338 return true;
3339 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3340 MCOperand::createExpr(LoExpr), IDLoc, STI);
3341 }
3342 return false;
3343 }
3344
3345 // if(!IsSingle)
3346 unsigned ATReg = getATReg(IDLoc);
3347 if (!ATReg)
3348 return true;
3349
3350 if (IsGPR) {
3351 if (LoImmOp64 == 0) {
3352 if(isABI_N32() || isABI_N64()) {
3353 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3354 IDLoc, Out, STI))
3355 return true;
3356 return false;
3357 } else {
3358 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3359 IDLoc, Out, STI))
3360 return true;
3361
3362 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3363 IDLoc, Out, STI))
3364 return true;
3365 return false;
3366 }
3367 }
3368
3369 MCSection *CS = getStreamer().getCurrentSectionOnly();
3370 MCSection *ReadOnlySection = getContext().getELFSection(
3371 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3372
3373 MCSymbol *Sym = getContext().createTempSymbol();
3374 const MCExpr *LoSym =
3375 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3376 const MipsMCExpr *LoExpr =
3377 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3378
3379 getStreamer().SwitchSection(ReadOnlySection);
3380 getStreamer().EmitLabel(Sym, IDLoc);
3381 getStreamer().EmitIntValue(HiImmOp64, 4);
3382 getStreamer().EmitIntValue(LoImmOp64, 4);
3383 getStreamer().SwitchSection(CS);
3384
3385 if(emitPartialAddress(TOut, IDLoc, Sym))
3386 return true;
3387 if(isABI_N64())
3388 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3389 MCOperand::createExpr(LoExpr), IDLoc, STI);
3390 else
3391 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3392 MCOperand::createExpr(LoExpr), IDLoc, STI);
3393
3394 if(isABI_N32() || isABI_N64())
3395 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3396 else {
3397 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3398 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3399 }
3400 return false;
3401 } else { // if(!IsGPR && !IsSingle)
3402 if ((LoImmOp64 == 0) &&
3403 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3404 // FIXME: In the case where the constant is zero, we can load the
3405 // register directly from the zero register.
3406 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3407 Out, STI))
3408 return true;
3409 if (isABI_N32() || isABI_N64())
3410 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3411 else if (hasMips32r2()) {
3412 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3413 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3414 } else {
3415 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3416 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3417 }
3418 return false;
3419 }
3420
3421 MCSection *CS = getStreamer().getCurrentSectionOnly();
3422 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3423 // where appropriate.
3424 MCSection *ReadOnlySection = getContext().getELFSection(
3425 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3426
3427 MCSymbol *Sym = getContext().createTempSymbol();
3428 const MCExpr *LoSym =
3429 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3430 const MipsMCExpr *LoExpr =
3431 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3432
3433 getStreamer().SwitchSection(ReadOnlySection);
3434 getStreamer().EmitLabel(Sym, IDLoc);
3435 getStreamer().EmitIntValue(HiImmOp64, 4);
3436 getStreamer().EmitIntValue(LoImmOp64, 4);
3437 getStreamer().SwitchSection(CS);
3438
3439 if(emitPartialAddress(TOut, IDLoc, Sym))
3440 return true;
3441 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3442 MCOperand::createExpr(LoExpr), IDLoc, STI);
3443 }
3444 return false;
3445}
3446
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003447bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3448 MCStreamer &Out,
3449 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003450 MipsTargetStreamer &TOut = getTargetStreamer();
3451
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003452 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3453 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003454
3455 MCOperand Offset = Inst.getOperand(0);
3456 if (Offset.isExpr()) {
3457 Inst.clear();
3458 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003459 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3460 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3461 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003462 } else {
3463 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003464 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003465 // If offset fits into 11 bits then this instruction becomes microMIPS
3466 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003467 if (inMicroMipsMode())
3468 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003469 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003470 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003471 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003472 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003473 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003474 Inst.clear();
3475 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003476 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3477 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3478 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003479 }
3480 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003481 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003482
Zoran Jovanovicada70912015-09-07 11:56:37 +00003483 // If .set reorder is active and branch instruction has a delay slot,
3484 // emit a NOP after it.
3485 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3486 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003487 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003488
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003489 return false;
3490}
3491
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003492bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3493 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003494 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003495 const MCOperand &DstRegOp = Inst.getOperand(0);
3496 assert(DstRegOp.isReg() && "expected register operand kind");
3497
3498 const MCOperand &ImmOp = Inst.getOperand(1);
3499 assert(ImmOp.isImm() && "expected immediate operand kind");
3500
3501 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003502 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3503 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003504
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003505 bool IsLikely = false;
3506
Toma Tabacue1e460d2015-06-11 10:36:10 +00003507 unsigned OpCode = 0;
3508 switch(Inst.getOpcode()) {
3509 case Mips::BneImm:
3510 OpCode = Mips::BNE;
3511 break;
3512 case Mips::BeqImm:
3513 OpCode = Mips::BEQ;
3514 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003515 case Mips::BEQLImmMacro:
3516 OpCode = Mips::BEQL;
3517 IsLikely = true;
3518 break;
3519 case Mips::BNELImmMacro:
3520 OpCode = Mips::BNEL;
3521 IsLikely = true;
3522 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003523 default:
3524 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3525 break;
3526 }
3527
3528 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003529 if (ImmValue == 0) {
3530 if (IsLikely) {
3531 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3532 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3533 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3534 } else
3535 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3536 STI);
3537 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003538 warnIfNoMacro(IDLoc);
3539
3540 unsigned ATReg = getATReg(IDLoc);
3541 if (!ATReg)
3542 return true;
3543
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003544 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003545 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003546 return true;
3547
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003548 if (IsLikely) {
3549 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3550 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3551 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3552 } else
3553 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003554 }
3555 return false;
3556}
3557
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003558void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Simon Atanasyana1882672018-05-24 07:36:11 +00003559 const MCSubtargetInfo *STI, bool IsLoad) {
Simon Atanasyanbe8a42e2018-05-24 07:36:06 +00003560 const MCOperand &DstRegOp = Inst.getOperand(0);
3561 assert(DstRegOp.isReg() && "expected register operand kind");
3562 const MCOperand &BaseRegOp = Inst.getOperand(1);
3563 assert(BaseRegOp.isReg() && "expected register operand kind");
3564 const MCOperand &OffsetOp = Inst.getOperand(2);
Daniel Sandersfba875f2016-04-29 13:43:45 +00003565
Simon Atanasyanbe8a42e2018-05-24 07:36:06 +00003566 MipsTargetStreamer &TOut = getTargetStreamer();
3567 unsigned DstReg = DstRegOp.getReg();
3568 unsigned BaseReg = BaseRegOp.getReg();
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003569 unsigned TmpReg = DstReg;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003570
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003571 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003572 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3573 unsigned DstRegClassID =
3574 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3575 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3576 (DstRegClassID == Mips::GPR64RegClassID);
3577
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00003578 if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003579 // At this point we need AT to perform the expansions
3580 // and we exit if it is not available.
3581 TmpReg = getATReg(IDLoc);
3582 if (!TmpReg)
3583 return;
3584 }
3585
Simon Atanasyana1882672018-05-24 07:36:11 +00003586 if (OffsetOp.isImm()) {
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00003587 int64_t LoOffset = OffsetOp.getImm() & 0xffff;
3588 int64_t HiOffset = OffsetOp.getImm() & ~0xffff;
3589
3590 // If msb of LoOffset is 1(negative number) we must increment
3591 // HiOffset to account for the sign-extension of the low part.
3592 if (LoOffset & 0x8000)
3593 HiOffset += 0x10000;
3594
3595 bool IsLargeOffset = HiOffset != 0;
3596
3597 if (IsLargeOffset) {
3598 bool Is32BitImm = (HiOffset >> 32) == 0;
3599 if (loadImmediate(HiOffset, TmpReg, Mips::NoRegister, Is32BitImm, true,
3600 IDLoc, Out, STI))
3601 return;
3602 }
3603
3604 if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)
3605 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg,
3606 BaseReg, IDLoc, STI);
3607 TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, LoOffset, IDLoc, STI);
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003608 } else {
3609 assert(OffsetOp.isExpr() && "expected expression operand kind");
3610 const MCExpr *ExprOffset = OffsetOp.getExpr();
3611 MCOperand LoOperand = MCOperand::createExpr(
3612 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3613 MCOperand HiOperand = MCOperand::createExpr(
3614 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00003615
3616 if (IsLoad)
3617 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3618 LoOperand, TmpReg, IDLoc, STI);
3619 else
3620 TOut.emitStoreWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3621 LoOperand, TmpReg, IDLoc, STI);
Daniel Sandersfba875f2016-04-29 13:43:45 +00003622 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003623}
3624
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003625bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3626 MCStreamer &Out,
3627 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003628 unsigned OpNum = Inst.getNumOperands();
3629 unsigned Opcode = Inst.getOpcode();
3630 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3631
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003632 assert(Inst.getOperand(OpNum - 1).isImm() &&
3633 Inst.getOperand(OpNum - 2).isReg() &&
3634 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003635
3636 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3637 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003638 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3639 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3640 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3641 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003642 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003643 if (inMicroMipsMode() && hasMips32r6())
3644 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3645 else
3646 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3647 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003648
3649 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003650 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003651 return false;
3652}
3653
Toma Tabacu1a108322015-06-17 13:20:24 +00003654bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003655 MCStreamer &Out,
3656 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003657 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003658 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003659 unsigned PseudoOpcode = Inst.getOpcode();
3660 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003661 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003662 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3663
3664 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003665 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003666
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003667 unsigned TrgReg;
3668 if (TrgOp.isReg())
3669 TrgReg = TrgOp.getReg();
3670 else if (TrgOp.isImm()) {
3671 warnIfNoMacro(IDLoc);
3672 EmittedNoMacroWarning = true;
3673
3674 TrgReg = getATReg(IDLoc);
3675 if (!TrgReg)
3676 return true;
3677
3678 switch(PseudoOpcode) {
3679 default:
3680 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3681 case Mips::BLTImmMacro:
3682 PseudoOpcode = Mips::BLT;
3683 break;
3684 case Mips::BLEImmMacro:
3685 PseudoOpcode = Mips::BLE;
3686 break;
3687 case Mips::BGEImmMacro:
3688 PseudoOpcode = Mips::BGE;
3689 break;
3690 case Mips::BGTImmMacro:
3691 PseudoOpcode = Mips::BGT;
3692 break;
3693 case Mips::BLTUImmMacro:
3694 PseudoOpcode = Mips::BLTU;
3695 break;
3696 case Mips::BLEUImmMacro:
3697 PseudoOpcode = Mips::BLEU;
3698 break;
3699 case Mips::BGEUImmMacro:
3700 PseudoOpcode = Mips::BGEU;
3701 break;
3702 case Mips::BGTUImmMacro:
3703 PseudoOpcode = Mips::BGTU;
3704 break;
3705 case Mips::BLTLImmMacro:
3706 PseudoOpcode = Mips::BLTL;
3707 break;
3708 case Mips::BLELImmMacro:
3709 PseudoOpcode = Mips::BLEL;
3710 break;
3711 case Mips::BGELImmMacro:
3712 PseudoOpcode = Mips::BGEL;
3713 break;
3714 case Mips::BGTLImmMacro:
3715 PseudoOpcode = Mips::BGTL;
3716 break;
3717 case Mips::BLTULImmMacro:
3718 PseudoOpcode = Mips::BLTUL;
3719 break;
3720 case Mips::BLEULImmMacro:
3721 PseudoOpcode = Mips::BLEUL;
3722 break;
3723 case Mips::BGEULImmMacro:
3724 PseudoOpcode = Mips::BGEUL;
3725 break;
3726 case Mips::BGTULImmMacro:
3727 PseudoOpcode = Mips::BGTUL;
3728 break;
3729 }
3730
3731 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003732 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003733 return true;
3734 }
3735
Toma Tabacu1a108322015-06-17 13:20:24 +00003736 switch (PseudoOpcode) {
3737 case Mips::BLT:
3738 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003739 case Mips::BLTL:
3740 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003741 AcceptsEquality = false;
3742 ReverseOrderSLT = false;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003743 IsUnsigned =
3744 ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003745 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003746 ZeroSrcOpcode = Mips::BGTZ;
3747 ZeroTrgOpcode = Mips::BLTZ;
3748 break;
3749 case Mips::BLE:
3750 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003751 case Mips::BLEL:
3752 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003753 AcceptsEquality = true;
3754 ReverseOrderSLT = true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003755 IsUnsigned =
3756 ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003757 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003758 ZeroSrcOpcode = Mips::BGEZ;
3759 ZeroTrgOpcode = Mips::BLEZ;
3760 break;
3761 case Mips::BGE:
3762 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003763 case Mips::BGEL:
3764 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003765 AcceptsEquality = true;
3766 ReverseOrderSLT = false;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003767 IsUnsigned =
3768 ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003769 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003770 ZeroSrcOpcode = Mips::BLEZ;
3771 ZeroTrgOpcode = Mips::BGEZ;
3772 break;
3773 case Mips::BGT:
3774 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003775 case Mips::BGTL:
3776 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003777 AcceptsEquality = false;
3778 ReverseOrderSLT = true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003779 IsUnsigned =
3780 ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003781 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003782 ZeroSrcOpcode = Mips::BLTZ;
3783 ZeroTrgOpcode = Mips::BGTZ;
3784 break;
3785 default:
3786 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3787 }
3788
Toma Tabacu1a108322015-06-17 13:20:24 +00003789 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3790 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3791 if (IsSrcRegZero && IsTrgRegZero) {
3792 // FIXME: All of these Opcode-specific if's are needed for compatibility
3793 // with GAS' behaviour. However, they may not generate the most efficient
3794 // code in some circumstances.
3795 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003796 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3797 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003798 return false;
3799 }
3800 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003801 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3802 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003803 Warning(IDLoc, "branch is always taken");
3804 return false;
3805 }
3806 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003807 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3808 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003809 Warning(IDLoc, "branch is always taken");
3810 return false;
3811 }
3812 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003813 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3814 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003815 return false;
3816 }
3817 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003818 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3819 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003820 return false;
3821 }
3822 if (AcceptsEquality) {
3823 // If both registers are $0 and the pseudo-branch accepts equality, it
3824 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003825 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3826 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003827 Warning(IDLoc, "branch is always taken");
3828 return false;
3829 }
3830 // If both registers are $0 and the pseudo-branch does not accept
3831 // equality, it will never be taken, so we don't have to emit anything.
3832 return false;
3833 }
3834 if (IsSrcRegZero || IsTrgRegZero) {
3835 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3836 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3837 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3838 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3839 // the pseudo-branch will never be taken, so we don't emit anything.
3840 // This only applies to unsigned pseudo-branches.
3841 return false;
3842 }
3843 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3844 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3845 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3846 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3847 // the pseudo-branch will always be taken, so we emit an unconditional
3848 // branch.
3849 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003850 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3851 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003852 Warning(IDLoc, "branch is always taken");
3853 return false;
3854 }
3855 if (IsUnsigned) {
3856 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3857 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3858 // the pseudo-branch will be taken only when the non-zero register is
3859 // different from 0, so we emit a BNEZ.
3860 //
3861 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3862 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3863 // the pseudo-branch will be taken only when the non-zero register is
3864 // equal to 0, so we emit a BEQZ.
3865 //
3866 // Because only BLEU and BGEU branch on equality, we can use the
3867 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003868 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3869 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3870 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003871 return false;
3872 }
3873 // If we have a signed pseudo-branch and one of the registers is $0,
3874 // we can use an appropriate compare-to-zero branch. We select which one
3875 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003876 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3877 IsSrcRegZero ? TrgReg : SrcReg,
3878 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003879 return false;
3880 }
3881
3882 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3883 // expansions. If it is not available, we return.
3884 unsigned ATRegNum = getATReg(IDLoc);
3885 if (!ATRegNum)
3886 return true;
3887
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003888 if (!EmittedNoMacroWarning)
3889 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003890
3891 // SLT fits well with 2 of our 4 pseudo-branches:
3892 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3893 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3894 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3895 // This is accomplished by using a BNEZ with the result of the SLT.
3896 //
3897 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
Hiroshi Inoue7f9f92f2018-02-22 07:48:29 +00003898 // and BLE with BGT), so we change the BNEZ into a BEQZ.
Toma Tabacu1a108322015-06-17 13:20:24 +00003899 // Because only BGE and BLE branch on equality, we can use the
3900 // AcceptsEquality variable to decide when to emit the BEQZ.
3901 // Note that the order of the SLT arguments doesn't change between
3902 // opposites.
3903 //
3904 // The same applies to the unsigned variants, except that SLTu is used
3905 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003906 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3907 ReverseOrderSLT ? TrgReg : SrcReg,
3908 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003909
Daniel Sandersa736b372016-04-29 13:33:12 +00003910 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3911 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3912 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3913 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003914 return false;
3915}
3916
Simon Dardis509da1a2017-02-13 16:06:48 +00003917// Expand a integer division macro.
3918//
3919// Notably we don't have to emit a warning when encountering $rt as the $zero
3920// register, or 0 as an immediate. processInstruction() has already done that.
3921//
3922// The destination register can only be $zero when expanding (S)DivIMacro or
3923// D(S)DivMacro.
3924
Stefan Maksimovic0a239982018-07-09 13:06:44 +00003925bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3926 const MCSubtargetInfo *STI, const bool IsMips64,
3927 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003928 MipsTargetStreamer &TOut = getTargetStreamer();
3929
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003930 warnIfNoMacro(IDLoc);
3931
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003932 const MCOperand &RdRegOp = Inst.getOperand(0);
3933 assert(RdRegOp.isReg() && "expected register operand kind");
3934 unsigned RdReg = RdRegOp.getReg();
3935
3936 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003937 assert(RsRegOp.isReg() && "expected register operand kind");
3938 unsigned RsReg = RsRegOp.getReg();
3939
Simon Dardis12850ee2017-01-31 10:49:24 +00003940 unsigned RtReg;
3941 int64_t ImmValue;
3942
3943 const MCOperand &RtOp = Inst.getOperand(2);
3944 assert((RtOp.isReg() || RtOp.isImm()) &&
3945 "expected register or immediate operand kind");
3946 if (RtOp.isReg())
3947 RtReg = RtOp.getReg();
3948 else
3949 ImmValue = RtOp.getImm();
3950
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003951 unsigned DivOp;
3952 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003953 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003954
3955 if (IsMips64) {
3956 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3957 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003958 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003959 } else {
3960 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3961 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003962 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003963 }
3964
3965 bool UseTraps = useTraps();
3966
Stefan Maksimovic0a239982018-07-09 13:06:44 +00003967 unsigned Opcode = Inst.getOpcode();
3968 bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro ||
3969 Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro ||
3970 Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro ||
3971 Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro;
3972
3973 bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro ||
3974 Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro ||
3975 Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro ||
3976 Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro;
3977
Simon Dardis12850ee2017-01-31 10:49:24 +00003978 if (RtOp.isImm()) {
3979 unsigned ATReg = getATReg(IDLoc);
3980 if (!ATReg)
3981 return true;
3982
3983 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003984 if (UseTraps)
3985 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3986 else
3987 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3988 return false;
3989 }
3990
Stefan Maksimovic0a239982018-07-09 13:06:44 +00003991 if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1)))) {
3992 TOut.emitRRR(Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI);
3993 return false;
3994 } else if (isDiv && ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003995 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003996 return false;
Stefan Maksimovic0a239982018-07-09 13:06:44 +00003997 } else if (isDiv && Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003998 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003999 return false;
4000 } else {
4001 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
4002 false, Inst.getLoc(), Out, STI))
4003 return true;
4004 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004005 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00004006 return false;
4007 }
4008 return true;
4009 }
4010
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004011 // If the macro expansion of (d)div(u) or (d)rem(u) would always trap or
4012 // break, insert the trap/break and exit. This gives a different result to
4013 // GAS. GAS has an inconsistency/missed optimization in that not all cases
4014 // are handled equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004015 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004016 if (UseTraps) {
4017 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004018 return false;
4019 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004020 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4021 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004022 }
4023
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004024 // (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does
4025 // not expand to macro sequence.
4026 if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) {
4027 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
4028 return false;
4029 }
4030
Simon Dardis509da1a2017-02-13 16:06:48 +00004031 // Temporary label for first branch traget
4032 MCContext &Context = TOut.getStreamer().getContext();
4033 MCSymbol *BrTarget;
4034 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004035
4036 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004037 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004038 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004039 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004040 BrTarget = Context.createTempSymbol();
4041 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4042 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004043 }
4044
Daniel Sandersa736b372016-04-29 13:33:12 +00004045 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004046
4047 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004048 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004049
4050 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004051 if (!UseTraps)
4052 TOut.getStreamer().EmitLabel(BrTarget);
4053
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004054 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004055 return false;
4056 }
4057
4058 unsigned ATReg = getATReg(IDLoc);
4059 if (!ATReg)
4060 return true;
4061
Simon Dardis509da1a2017-02-13 16:06:48 +00004062 if (!UseTraps)
4063 TOut.getStreamer().EmitLabel(BrTarget);
4064
Daniel Sandersa736b372016-04-29 13:33:12 +00004065 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004066
4067 // Temporary label for the second branch target.
4068 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4069 MCOperand LabelOpEnd =
4070 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4071
4072 // Branch to the mflo instruction.
4073 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4074
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004075 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004076 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004077 TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004078 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004079 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004080 }
4081
4082 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004083 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004084 else {
4085 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004086 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004087 TOut.emitNop(IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004088 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004089 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004090
4091 TOut.getStreamer().EmitLabel(BrTargetEnd);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004092 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004093 return false;
4094}
4095
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004096bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004097 SMLoc IDLoc, MCStreamer &Out,
4098 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004099 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004100
4101 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4102 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4103 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4104
4105 unsigned FirstReg = Inst.getOperand(0).getReg();
4106 unsigned SecondReg = Inst.getOperand(1).getReg();
4107 unsigned ThirdReg = Inst.getOperand(2).getReg();
4108
4109 if (hasMips1() && !hasMips2()) {
4110 unsigned ATReg = getATReg(IDLoc);
4111 if (!ATReg)
4112 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004113 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4114 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4115 TOut.emitNop(IDLoc, STI);
4116 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4117 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4118 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4119 TOut.emitNop(IDLoc, STI);
4120 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4121 : Mips::CVT_W_S,
4122 FirstReg, SecondReg, IDLoc, STI);
4123 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4124 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004125 return false;
4126 }
4127
Daniel Sandersa736b372016-04-29 13:33:12 +00004128 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4129 : Mips::TRUNC_W_S,
4130 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004131
4132 return false;
4133}
4134
Daniel Sanders6394ee52015-10-15 14:52:58 +00004135bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004136 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004137 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004138 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004139 }
4140
Toma Tabacud88d79c2015-06-23 14:39:42 +00004141 const MCOperand &DstRegOp = Inst.getOperand(0);
4142 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004143 const MCOperand &SrcRegOp = Inst.getOperand(1);
4144 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004145 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4146 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4147
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004148 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004149 unsigned DstReg = DstRegOp.getReg();
4150 unsigned SrcReg = SrcRegOp.getReg();
4151 int64_t OffsetValue = OffsetImmOp.getImm();
4152
4153 // NOTE: We always need AT for ULHU, as it is always used as the source
4154 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004155 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004156 unsigned ATReg = getATReg(IDLoc);
4157 if (!ATReg)
4158 return true;
4159
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004160 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4161 if (IsLargeOffset) {
4162 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4163 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004164 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004165 }
4166
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004167 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4168 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4169 if (isLittle())
4170 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004171
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004172 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4173 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004174
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004175 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4176 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004177
Daniel Sandersa736b372016-04-29 13:33:12 +00004178 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004179 FirstOffset, IDLoc, STI);
4180 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004181 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004182 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004183
4184 return false;
4185}
4186
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004187bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004188 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004189 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004190 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004191 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004192
4193 const MCOperand &DstRegOp = Inst.getOperand(0);
4194 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004195 const MCOperand &SrcRegOp = Inst.getOperand(1);
4196 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004197 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4198 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4199
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004200 MipsTargetStreamer &TOut = getTargetStreamer();
4201 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004202 unsigned SrcReg = SrcRegOp.getReg();
4203 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004204
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004205 warnIfNoMacro(IDLoc);
4206 unsigned ATReg = getATReg(IDLoc);
4207 if (!ATReg)
4208 return true;
4209
4210 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4211 if (IsLargeOffset) {
4212 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4213 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004214 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004215 }
4216
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004217 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4218 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4219 if (isLittle())
4220 std::swap(FirstOffset, SecondOffset);
4221
4222 if (IsLargeOffset) {
4223 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4224 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4225 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4226 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4227 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4228 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004229 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004230 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4231 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4232 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004233 }
4234
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004235 return false;
4236}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004237
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004238bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4239 const MCSubtargetInfo *STI) {
4240 if (hasMips32r6() || hasMips64r6()) {
4241 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4242 }
4243
4244 const MCOperand &DstRegOp = Inst.getOperand(0);
4245 assert(DstRegOp.isReg() && "expected register operand kind");
4246 const MCOperand &SrcRegOp = Inst.getOperand(1);
4247 assert(SrcRegOp.isReg() && "expected register operand kind");
4248 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4249 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4250
4251 MipsTargetStreamer &TOut = getTargetStreamer();
4252 unsigned DstReg = DstRegOp.getReg();
4253 unsigned SrcReg = SrcRegOp.getReg();
4254 int64_t OffsetValue = OffsetImmOp.getImm();
4255
4256 // Compute left/right load/store offsets.
4257 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4258 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4259 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4260 if (isLittle())
4261 std::swap(LxlOffset, LxrOffset);
4262
4263 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4264 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4265 unsigned TmpReg = SrcReg;
4266 if (IsLargeOffset || DoMove) {
4267 warnIfNoMacro(IDLoc);
4268 TmpReg = getATReg(IDLoc);
4269 if (!TmpReg)
4270 return true;
4271 }
4272
4273 if (IsLargeOffset) {
4274 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4275 IDLoc, Out, STI))
4276 return true;
4277 }
4278
4279 if (DoMove)
4280 std::swap(DstReg, TmpReg);
4281
4282 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4283 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4284 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4285 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4286
4287 if (DoMove)
4288 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004289
4290 return false;
4291}
4292
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004293bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004294 MCStreamer &Out,
4295 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004296 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004297
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004298 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4299 assert(Inst.getOperand(0).isReg() &&
4300 Inst.getOperand(1).isReg() &&
4301 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004302
4303 unsigned ATReg = Mips::NoRegister;
4304 unsigned FinalDstReg = Mips::NoRegister;
4305 unsigned DstReg = Inst.getOperand(0).getReg();
4306 unsigned SrcReg = Inst.getOperand(1).getReg();
4307 int64_t ImmValue = Inst.getOperand(2).getImm();
4308
Simon Dardisaa208812017-02-24 14:34:32 +00004309 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004310
4311 unsigned FinalOpcode = Inst.getOpcode();
4312
4313 if (DstReg == SrcReg) {
4314 ATReg = getATReg(Inst.getLoc());
4315 if (!ATReg)
4316 return true;
4317 FinalDstReg = DstReg;
4318 DstReg = ATReg;
4319 }
4320
Simon Atanasyan478220f2018-05-24 07:36:00 +00004321 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false,
4322 Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004323 switch (FinalOpcode) {
4324 default:
4325 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004326 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004327 FinalOpcode = Mips::ADD;
4328 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004329 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004330 FinalOpcode = Mips::ADDu;
4331 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004332 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004333 FinalOpcode = Mips::AND;
4334 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004335 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004336 FinalOpcode = Mips::NOR;
4337 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004338 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004339 FinalOpcode = Mips::OR;
4340 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004341 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004342 FinalOpcode = Mips::SLT;
4343 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004344 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004345 FinalOpcode = Mips::SLTu;
4346 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004347 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004348 FinalOpcode = Mips::XOR;
4349 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004350 case Mips::ADDi_MM:
4351 FinalOpcode = Mips::ADD_MM;
4352 break;
4353 case Mips::ADDiu_MM:
4354 FinalOpcode = Mips::ADDu_MM;
4355 break;
4356 case Mips::ANDi_MM:
4357 FinalOpcode = Mips::AND_MM;
4358 break;
4359 case Mips::ORi_MM:
4360 FinalOpcode = Mips::OR_MM;
4361 break;
4362 case Mips::SLTi_MM:
4363 FinalOpcode = Mips::SLT_MM;
4364 break;
4365 case Mips::SLTiu_MM:
4366 FinalOpcode = Mips::SLTu_MM;
4367 break;
4368 case Mips::XORi_MM:
4369 FinalOpcode = Mips::XOR_MM;
4370 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004371 case Mips::ANDi64:
4372 FinalOpcode = Mips::AND64;
4373 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004374 case Mips::NORImm64:
4375 FinalOpcode = Mips::NOR64;
4376 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004377 case Mips::ORi64:
4378 FinalOpcode = Mips::OR64;
4379 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004380 case Mips::SLTImm64:
4381 FinalOpcode = Mips::SLT64;
4382 break;
4383 case Mips::SLTUImm64:
4384 FinalOpcode = Mips::SLTu64;
4385 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004386 case Mips::XORi64:
4387 FinalOpcode = Mips::XOR64;
4388 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004389 }
4390
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004391 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004392 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004393 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004394 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004395 return false;
4396 }
4397 return true;
4398}
4399
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004400bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4401 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004402 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004403 unsigned ATReg = Mips::NoRegister;
4404 unsigned DReg = Inst.getOperand(0).getReg();
4405 unsigned SReg = Inst.getOperand(1).getReg();
4406 unsigned TReg = Inst.getOperand(2).getReg();
4407 unsigned TmpReg = DReg;
4408
4409 unsigned FirstShift = Mips::NOP;
4410 unsigned SecondShift = Mips::NOP;
4411
4412 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004413 if (DReg == SReg) {
4414 TmpReg = getATReg(Inst.getLoc());
4415 if (!TmpReg)
4416 return true;
4417 }
4418
4419 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004420 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4421 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004422 return false;
4423 }
4424
4425 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004426 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004427 return false;
4428 }
4429
4430 return true;
4431 }
4432
4433 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004434 switch (Inst.getOpcode()) {
4435 default:
4436 llvm_unreachable("unexpected instruction opcode");
4437 case Mips::ROL:
4438 FirstShift = Mips::SRLV;
4439 SecondShift = Mips::SLLV;
4440 break;
4441 case Mips::ROR:
4442 FirstShift = Mips::SLLV;
4443 SecondShift = Mips::SRLV;
4444 break;
4445 }
4446
4447 ATReg = getATReg(Inst.getLoc());
4448 if (!ATReg)
4449 return true;
4450
Daniel Sandersa736b372016-04-29 13:33:12 +00004451 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4452 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4453 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4454 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004455
4456 return false;
4457 }
4458
4459 return true;
4460}
4461
4462bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004463 MCStreamer &Out,
4464 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004465 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004466 unsigned ATReg = Mips::NoRegister;
4467 unsigned DReg = Inst.getOperand(0).getReg();
4468 unsigned SReg = Inst.getOperand(1).getReg();
4469 int64_t ImmValue = Inst.getOperand(2).getImm();
4470
4471 unsigned FirstShift = Mips::NOP;
4472 unsigned SecondShift = Mips::NOP;
4473
4474 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004475 if (Inst.getOpcode() == Mips::ROLImm) {
4476 uint64_t MaxShift = 32;
4477 uint64_t ShiftValue = ImmValue;
4478 if (ImmValue != 0)
4479 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004480 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004481 return false;
4482 }
4483
4484 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004485 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004486 return false;
4487 }
4488
4489 return true;
4490 }
4491
4492 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004493 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004494 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004495 return false;
4496 }
4497
4498 switch (Inst.getOpcode()) {
4499 default:
4500 llvm_unreachable("unexpected instruction opcode");
4501 case Mips::ROLImm:
4502 FirstShift = Mips::SLL;
4503 SecondShift = Mips::SRL;
4504 break;
4505 case Mips::RORImm:
4506 FirstShift = Mips::SRL;
4507 SecondShift = Mips::SLL;
4508 break;
4509 }
4510
4511 ATReg = getATReg(Inst.getLoc());
4512 if (!ATReg)
4513 return true;
4514
Daniel Sandersa736b372016-04-29 13:33:12 +00004515 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4516 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4517 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004518
4519 return false;
4520 }
4521
4522 return true;
4523}
4524
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004525bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4526 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004527 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004528 unsigned ATReg = Mips::NoRegister;
4529 unsigned DReg = Inst.getOperand(0).getReg();
4530 unsigned SReg = Inst.getOperand(1).getReg();
4531 unsigned TReg = Inst.getOperand(2).getReg();
4532 unsigned TmpReg = DReg;
4533
4534 unsigned FirstShift = Mips::NOP;
4535 unsigned SecondShift = Mips::NOP;
4536
4537 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004538 if (TmpReg == SReg) {
4539 TmpReg = getATReg(Inst.getLoc());
4540 if (!TmpReg)
4541 return true;
4542 }
4543
4544 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004545 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4546 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004547 return false;
4548 }
4549
4550 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004551 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004552 return false;
4553 }
4554
4555 return true;
4556 }
4557
4558 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004559 switch (Inst.getOpcode()) {
4560 default:
4561 llvm_unreachable("unexpected instruction opcode");
4562 case Mips::DROL:
4563 FirstShift = Mips::DSRLV;
4564 SecondShift = Mips::DSLLV;
4565 break;
4566 case Mips::DROR:
4567 FirstShift = Mips::DSLLV;
4568 SecondShift = Mips::DSRLV;
4569 break;
4570 }
4571
4572 ATReg = getATReg(Inst.getLoc());
4573 if (!ATReg)
4574 return true;
4575
Daniel Sandersa736b372016-04-29 13:33:12 +00004576 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4577 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4578 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4579 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004580
4581 return false;
4582 }
4583
4584 return true;
4585}
4586
4587bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004588 MCStreamer &Out,
4589 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004590 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004591 unsigned ATReg = Mips::NoRegister;
4592 unsigned DReg = Inst.getOperand(0).getReg();
4593 unsigned SReg = Inst.getOperand(1).getReg();
4594 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4595
4596 unsigned FirstShift = Mips::NOP;
4597 unsigned SecondShift = Mips::NOP;
4598
4599 MCInst TmpInst;
4600
4601 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004602 unsigned FinalOpcode = Mips::NOP;
4603 if (ImmValue == 0)
4604 FinalOpcode = Mips::DROTR;
4605 else if (ImmValue % 32 == 0)
4606 FinalOpcode = Mips::DROTR32;
4607 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4608 if (Inst.getOpcode() == Mips::DROLImm)
4609 FinalOpcode = Mips::DROTR32;
4610 else
4611 FinalOpcode = Mips::DROTR;
4612 } else if (ImmValue >= 33) {
4613 if (Inst.getOpcode() == Mips::DROLImm)
4614 FinalOpcode = Mips::DROTR;
4615 else
4616 FinalOpcode = Mips::DROTR32;
4617 }
4618
4619 uint64_t ShiftValue = ImmValue % 32;
4620 if (Inst.getOpcode() == Mips::DROLImm)
4621 ShiftValue = (32 - ImmValue % 32) % 32;
4622
Daniel Sandersa736b372016-04-29 13:33:12 +00004623 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004624
4625 return false;
4626 }
4627
4628 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004629 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004630 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004631 return false;
4632 }
4633
4634 switch (Inst.getOpcode()) {
4635 default:
4636 llvm_unreachable("unexpected instruction opcode");
4637 case Mips::DROLImm:
4638 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4639 FirstShift = Mips::DSLL;
4640 SecondShift = Mips::DSRL32;
4641 }
4642 if (ImmValue == 32) {
4643 FirstShift = Mips::DSLL32;
4644 SecondShift = Mips::DSRL32;
4645 }
4646 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4647 FirstShift = Mips::DSLL32;
4648 SecondShift = Mips::DSRL;
4649 }
4650 break;
4651 case Mips::DRORImm:
4652 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4653 FirstShift = Mips::DSRL;
4654 SecondShift = Mips::DSLL32;
4655 }
4656 if (ImmValue == 32) {
4657 FirstShift = Mips::DSRL32;
4658 SecondShift = Mips::DSLL32;
4659 }
4660 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4661 FirstShift = Mips::DSRL32;
4662 SecondShift = Mips::DSLL;
4663 }
4664 break;
4665 }
4666
4667 ATReg = getATReg(Inst.getLoc());
4668 if (!ATReg)
4669 return true;
4670
Daniel Sandersa736b372016-04-29 13:33:12 +00004671 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4672 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4673 Inst.getLoc(), STI);
4674 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004675
4676 return false;
4677 }
4678
4679 return true;
4680}
4681
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004682bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4683 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004684 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004685 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4686 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4687
Daniel Sandersa736b372016-04-29 13:33:12 +00004688 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004689 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004690 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004691 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004692 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4693 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004694
4695 return false;
4696}
4697
Simon Dardis3c82a642017-02-08 16:25:05 +00004698bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4699 const MCSubtargetInfo *STI) {
4700 MipsTargetStreamer &TOut = getTargetStreamer();
4701 unsigned ATReg = Mips::NoRegister;
4702 unsigned DstReg = Inst.getOperand(0).getReg();
4703 unsigned SrcReg = Inst.getOperand(1).getReg();
4704 int32_t ImmValue = Inst.getOperand(2).getImm();
4705
4706 ATReg = getATReg(IDLoc);
4707 if (!ATReg)
4708 return true;
4709
Simon Atanasyan478220f2018-05-24 07:36:00 +00004710 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out,
4711 STI);
Simon Dardis3c82a642017-02-08 16:25:05 +00004712
4713 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4714 SrcReg, ATReg, IDLoc, STI);
4715
4716 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4717
4718 return false;
4719}
4720
4721bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4722 const MCSubtargetInfo *STI) {
4723 MipsTargetStreamer &TOut = getTargetStreamer();
4724 unsigned ATReg = Mips::NoRegister;
4725 unsigned DstReg = Inst.getOperand(0).getReg();
4726 unsigned SrcReg = Inst.getOperand(1).getReg();
4727 unsigned TmpReg = Inst.getOperand(2).getReg();
4728
4729 ATReg = getATReg(Inst.getLoc());
4730 if (!ATReg)
4731 return true;
4732
4733 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4734 SrcReg, TmpReg, IDLoc, STI);
4735
4736 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4737
4738 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4739 DstReg, DstReg, 0x1F, IDLoc, STI);
4740
4741 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4742
4743 if (useTraps()) {
4744 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4745 } else {
4746 MCContext & Context = TOut.getStreamer().getContext();
4747 MCSymbol * BrTarget = Context.createTempSymbol();
4748 MCOperand LabelOp =
4749 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4750
4751 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4752 if (AssemblerOptions.back()->isReorder())
4753 TOut.emitNop(IDLoc, STI);
4754 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4755
4756 TOut.getStreamer().EmitLabel(BrTarget);
4757 }
4758 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4759
4760 return false;
4761}
4762
4763bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4764 const MCSubtargetInfo *STI) {
4765 MipsTargetStreamer &TOut = getTargetStreamer();
4766 unsigned ATReg = Mips::NoRegister;
4767 unsigned DstReg = Inst.getOperand(0).getReg();
4768 unsigned SrcReg = Inst.getOperand(1).getReg();
4769 unsigned TmpReg = Inst.getOperand(2).getReg();
4770
4771 ATReg = getATReg(IDLoc);
4772 if (!ATReg)
4773 return true;
4774
4775 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4776 SrcReg, TmpReg, IDLoc, STI);
4777
4778 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4779 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4780 if (useTraps()) {
4781 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4782 } else {
4783 MCContext & Context = TOut.getStreamer().getContext();
4784 MCSymbol * BrTarget = Context.createTempSymbol();
4785 MCOperand LabelOp =
4786 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4787
4788 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4789 if (AssemblerOptions.back()->isReorder())
4790 TOut.emitNop(IDLoc, STI);
4791 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4792
4793 TOut.getStreamer().EmitLabel(BrTarget);
4794 }
4795
4796 return false;
4797}
4798
4799bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4800 const MCSubtargetInfo *STI) {
4801 MipsTargetStreamer &TOut = getTargetStreamer();
4802 unsigned DstReg = Inst.getOperand(0).getReg();
4803 unsigned SrcReg = Inst.getOperand(1).getReg();
4804 unsigned TmpReg = Inst.getOperand(2).getReg();
4805
4806 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4807 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4808
4809 return false;
4810}
4811
Simon Dardisaff4d142016-10-18 14:28:00 +00004812// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4813// lw $<reg+1>>, offset+4($reg2)'
4814// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4815// sw $<reg+1>>, offset+4($reg2)'
4816// for O32.
4817bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4818 MCStreamer &Out,
4819 const MCSubtargetInfo *STI,
4820 bool IsLoad) {
4821 if (!isABI_O32())
4822 return true;
4823
4824 warnIfNoMacro(IDLoc);
4825
4826 MipsTargetStreamer &TOut = getTargetStreamer();
4827 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4828 unsigned FirstReg = Inst.getOperand(0).getReg();
4829 unsigned SecondReg = nextReg(FirstReg);
4830 unsigned BaseReg = Inst.getOperand(1).getReg();
4831 if (!SecondReg)
4832 return true;
4833
4834 warnIfRegIndexIsAT(FirstReg, IDLoc);
4835
4836 assert(Inst.getOperand(2).isImm() &&
4837 "Offset for load macro is not immediate!");
4838
4839 MCOperand &FirstOffset = Inst.getOperand(2);
4840 signed NextOffset = FirstOffset.getImm() + 4;
4841 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4842
4843 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4844 return true;
4845
4846 // For loads, clobber the base register with the second load instead of the
4847 // first if the BaseReg == FirstReg.
4848 if (FirstReg != BaseReg || !IsLoad) {
4849 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4850 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4851 } else {
4852 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4853 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4854 }
4855
4856 return false;
4857}
4858
Simon Dardis43115a12016-11-21 20:30:41 +00004859bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4860 const MCSubtargetInfo *STI) {
4861
4862 warnIfNoMacro(IDLoc);
4863 MipsTargetStreamer &TOut = getTargetStreamer();
4864
4865 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4866 Inst.getOperand(2).getReg() != Mips::ZERO) {
4867 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4868 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4869 IDLoc, STI);
4870 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4871 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4872 return false;
4873 }
4874
4875 unsigned Reg = 0;
4876 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4877 Reg = Inst.getOperand(2).getReg();
4878 } else {
4879 Reg = Inst.getOperand(1).getReg();
4880 }
4881 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4882 return false;
4883}
4884
4885bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4886 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004887 warnIfNoMacro(IDLoc);
4888 MipsTargetStreamer &TOut = getTargetStreamer();
4889
4890 unsigned Opc;
4891 int64_t Imm = Inst.getOperand(2).getImm();
4892 unsigned Reg = Inst.getOperand(1).getReg();
4893
4894 if (Imm == 0) {
4895 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4896 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4897 return false;
4898 } else {
4899
4900 if (Reg == Mips::ZERO) {
4901 Warning(IDLoc, "comparison is always false");
4902 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4903 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4904 return false;
4905 }
4906
4907 if (Imm > -0x8000 && Imm < 0) {
4908 Imm = -Imm;
4909 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4910 } else {
4911 Opc = Mips::XORi;
4912 }
4913 }
4914 if (!isUInt<16>(Imm)) {
4915 unsigned ATReg = getATReg(IDLoc);
4916 if (!ATReg)
4917 return true;
4918
4919 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4920 Out, STI))
4921 return true;
4922
4923 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4924 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4925 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4926 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4927 return false;
4928 }
4929
4930 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4931 Imm, IDLoc, STI);
4932 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4933 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4934 return false;
4935}
4936
Simon Dardisde5ed0c2017-11-14 22:26:42 +00004937// Map the DSP accumulator and control register to the corresponding gpr
4938// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
4939// do not map the DSP registers contigously to gpr registers.
4940static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
4941 switch (Inst.getOpcode()) {
4942 case Mips::MFTLO:
4943 case Mips::MTTLO:
4944 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4945 case Mips::AC0:
4946 return Mips::ZERO;
4947 case Mips::AC1:
4948 return Mips::A0;
4949 case Mips::AC2:
4950 return Mips::T0;
4951 case Mips::AC3:
4952 return Mips::T4;
4953 default:
4954 llvm_unreachable("Unknown register for 'mttr' alias!");
4955 }
4956 case Mips::MFTHI:
4957 case Mips::MTTHI:
4958 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4959 case Mips::AC0:
4960 return Mips::AT;
4961 case Mips::AC1:
4962 return Mips::A1;
4963 case Mips::AC2:
4964 return Mips::T1;
4965 case Mips::AC3:
4966 return Mips::T5;
4967 default:
4968 llvm_unreachable("Unknown register for 'mttr' alias!");
4969 }
4970 case Mips::MFTACX:
4971 case Mips::MTTACX:
4972 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4973 case Mips::AC0:
4974 return Mips::V0;
4975 case Mips::AC1:
4976 return Mips::A2;
4977 case Mips::AC2:
4978 return Mips::T2;
4979 case Mips::AC3:
4980 return Mips::T6;
4981 default:
4982 llvm_unreachable("Unknown register for 'mttr' alias!");
4983 }
4984 case Mips::MFTDSP:
4985 case Mips::MTTDSP:
4986 return Mips::S0;
4987 default:
4988 llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
4989 }
4990}
4991
4992// Map the floating point register operand to the corresponding register
4993// operand.
4994static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
4995 switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
4996 case Mips::F0: return Mips::ZERO;
4997 case Mips::F1: return Mips::AT;
4998 case Mips::F2: return Mips::V0;
4999 case Mips::F3: return Mips::V1;
5000 case Mips::F4: return Mips::A0;
5001 case Mips::F5: return Mips::A1;
5002 case Mips::F6: return Mips::A2;
5003 case Mips::F7: return Mips::A3;
5004 case Mips::F8: return Mips::T0;
5005 case Mips::F9: return Mips::T1;
5006 case Mips::F10: return Mips::T2;
5007 case Mips::F11: return Mips::T3;
5008 case Mips::F12: return Mips::T4;
5009 case Mips::F13: return Mips::T5;
5010 case Mips::F14: return Mips::T6;
5011 case Mips::F15: return Mips::T7;
5012 case Mips::F16: return Mips::S0;
5013 case Mips::F17: return Mips::S1;
5014 case Mips::F18: return Mips::S2;
5015 case Mips::F19: return Mips::S3;
5016 case Mips::F20: return Mips::S4;
5017 case Mips::F21: return Mips::S5;
5018 case Mips::F22: return Mips::S6;
5019 case Mips::F23: return Mips::S7;
5020 case Mips::F24: return Mips::T8;
5021 case Mips::F25: return Mips::T9;
5022 case Mips::F26: return Mips::K0;
5023 case Mips::F27: return Mips::K1;
5024 case Mips::F28: return Mips::GP;
5025 case Mips::F29: return Mips::SP;
5026 case Mips::F30: return Mips::FP;
5027 case Mips::F31: return Mips::RA;
5028 default: llvm_unreachable("Unknown register for mttc1 alias!");
5029 }
5030}
5031
5032// Map the coprocessor operand the corresponding gpr register operand.
5033static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
5034 switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
5035 case Mips::COP00: return Mips::ZERO;
5036 case Mips::COP01: return Mips::AT;
5037 case Mips::COP02: return Mips::V0;
5038 case Mips::COP03: return Mips::V1;
5039 case Mips::COP04: return Mips::A0;
5040 case Mips::COP05: return Mips::A1;
5041 case Mips::COP06: return Mips::A2;
5042 case Mips::COP07: return Mips::A3;
5043 case Mips::COP08: return Mips::T0;
5044 case Mips::COP09: return Mips::T1;
5045 case Mips::COP010: return Mips::T2;
5046 case Mips::COP011: return Mips::T3;
5047 case Mips::COP012: return Mips::T4;
5048 case Mips::COP013: return Mips::T5;
5049 case Mips::COP014: return Mips::T6;
5050 case Mips::COP015: return Mips::T7;
5051 case Mips::COP016: return Mips::S0;
5052 case Mips::COP017: return Mips::S1;
5053 case Mips::COP018: return Mips::S2;
5054 case Mips::COP019: return Mips::S3;
5055 case Mips::COP020: return Mips::S4;
5056 case Mips::COP021: return Mips::S5;
5057 case Mips::COP022: return Mips::S6;
5058 case Mips::COP023: return Mips::S7;
5059 case Mips::COP024: return Mips::T8;
5060 case Mips::COP025: return Mips::T9;
5061 case Mips::COP026: return Mips::K0;
5062 case Mips::COP027: return Mips::K1;
5063 case Mips::COP028: return Mips::GP;
5064 case Mips::COP029: return Mips::SP;
5065 case Mips::COP030: return Mips::FP;
5066 case Mips::COP031: return Mips::RA;
5067 default: llvm_unreachable("Unknown register for mttc0 alias!");
5068 }
5069}
5070
5071/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
5072/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
5073bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5074 const MCSubtargetInfo *STI) {
5075 MipsTargetStreamer &TOut = getTargetStreamer();
5076 unsigned rd = 0;
5077 unsigned u = 1;
5078 unsigned sel = 0;
5079 unsigned h = 0;
5080 bool IsMFTR = false;
5081 switch (Inst.getOpcode()) {
5082 case Mips::MFTC0:
5083 IsMFTR = true;
5084 LLVM_FALLTHROUGH;
5085 case Mips::MTTC0:
5086 u = 0;
5087 rd = getRegisterForMxtrC0(Inst, IsMFTR);
5088 sel = Inst.getOperand(2).getImm();
5089 break;
5090 case Mips::MFTGPR:
5091 IsMFTR = true;
5092 LLVM_FALLTHROUGH;
5093 case Mips::MTTGPR:
5094 rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
5095 break;
5096 case Mips::MFTLO:
5097 case Mips::MFTHI:
5098 case Mips::MFTACX:
5099 case Mips::MFTDSP:
5100 IsMFTR = true;
5101 LLVM_FALLTHROUGH;
5102 case Mips::MTTLO:
5103 case Mips::MTTHI:
5104 case Mips::MTTACX:
5105 case Mips::MTTDSP:
5106 rd = getRegisterForMxtrDSP(Inst, IsMFTR);
5107 sel = 1;
5108 break;
5109 case Mips::MFTHC1:
5110 h = 1;
5111 LLVM_FALLTHROUGH;
5112 case Mips::MFTC1:
5113 IsMFTR = true;
5114 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5115 sel = 2;
5116 break;
5117 case Mips::MTTHC1:
5118 h = 1;
5119 LLVM_FALLTHROUGH;
5120 case Mips::MTTC1:
5121 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5122 sel = 2;
5123 break;
5124 case Mips::CFTC1:
5125 IsMFTR = true;
5126 LLVM_FALLTHROUGH;
5127 case Mips::CTTC1:
5128 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5129 sel = 3;
5130 break;
5131 }
5132 unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
5133 unsigned Op1 =
5134 IsMFTR ? rd
5135 : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
5136 : Inst.getOperand(0).getReg());
5137
5138 TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
5139 STI);
5140 return false;
5141}
5142
Daniel Sandersc5537422016-07-27 13:49:44 +00005143unsigned
5144MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
5145 const OperandVector &Operands) {
5146 switch (Inst.getOpcode()) {
5147 default:
5148 return Match_Success;
5149 case Mips::DATI:
5150 case Mips::DAHI:
Daniel Sandersb23005e2016-07-28 15:59:06 +00005151 if (static_cast<MipsOperand &>(*Operands[1])
5152 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
5153 return Match_Success;
5154 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00005155 }
5156}
Simon Dardis730fdb72017-01-16 13:55:58 +00005157
Matheus Almeida595fcab2014-06-11 15:05:56 +00005158unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00005159 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00005160 // As described by the MIPSR6 spec, daui must not use the zero operand for
5161 // its source operand.
5162 case Mips::DAUI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00005163 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5164 Inst.getOperand(1).getReg() == Mips::ZERO_64)
5165 return Match_RequiresNoZeroRegister;
5166 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00005167 // As described by the Mips32r2 spec, the registers Rd and Rs for
5168 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00005169 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00005170 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00005171 case Mips::JALR_HB:
Simon Dardis7bc8ad52018-02-21 00:06:53 +00005172 case Mips::JALR_HB64:
Simon Dardisb60833c2016-05-31 17:34:42 +00005173 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00005174 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00005175 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5176 return Match_RequiresDifferentSrcAndDst;
5177 return Match_Success;
5178 case Mips::LWP_MM:
Simon Dardisb60833c2016-05-31 17:34:42 +00005179 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
5180 return Match_RequiresDifferentSrcAndDst;
5181 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00005182 case Mips::SYNC:
5183 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
5184 return Match_NonZeroOperandForSync;
5185 return Match_Success;
Simon Dardis52ae4f02018-03-07 11:39:48 +00005186 case Mips::MFC0:
5187 case Mips::MTC0:
5188 case Mips::MTC2:
5189 case Mips::MFC2:
5190 if (Inst.getOperand(2).getImm() != 0 && !hasMips32())
5191 return Match_NonZeroOperandForMTCX;
5192 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005193 // As described the MIPSR6 spec, the compact branches that compare registers
5194 // must:
5195 // a) Not use the zero register.
5196 // b) Not use the same register twice.
5197 // c) rs < rt for bnec, beqc.
5198 // NB: For this case, the encoding will swap the operands as their
5199 // ordering doesn't matter. GAS performs this transformation too.
5200 // Hence, that constraint does not have to be enforced.
5201 //
5202 // The compact branches that branch iff the signed addition of two registers
5203 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
5204 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005205 case Mips::BLEZC: case Mips::BLEZC_MMR6:
5206 case Mips::BGEZC: case Mips::BGEZC_MMR6:
5207 case Mips::BGTZC: case Mips::BGTZC_MMR6:
5208 case Mips::BLTZC: case Mips::BLTZC_MMR6:
5209 case Mips::BEQZC: case Mips::BEQZC_MMR6:
5210 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005211 case Mips::BLEZC64:
5212 case Mips::BGEZC64:
5213 case Mips::BGTZC64:
5214 case Mips::BLTZC64:
5215 case Mips::BEQZC64:
5216 case Mips::BNEZC64:
5217 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5218 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005219 return Match_RequiresNoZeroRegister;
5220 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005221 case Mips::BGEC: case Mips::BGEC_MMR6:
5222 case Mips::BLTC: case Mips::BLTC_MMR6:
5223 case Mips::BGEUC: case Mips::BGEUC_MMR6:
5224 case Mips::BLTUC: case Mips::BLTUC_MMR6:
5225 case Mips::BEQC: case Mips::BEQC_MMR6:
5226 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005227 case Mips::BGEC64:
5228 case Mips::BLTC64:
5229 case Mips::BGEUC64:
5230 case Mips::BLTUC64:
5231 case Mips::BEQC64:
5232 case Mips::BNEC64:
5233 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5234 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005235 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00005236 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5237 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005238 return Match_RequiresNoZeroRegister;
5239 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5240 return Match_RequiresDifferentOperands;
5241 return Match_Success;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005242 case Mips::DINS: {
Simon Dardis55e44672017-09-14 17:27:53 +00005243 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5244 "Operands must be immediates for dins!");
5245 const signed Pos = Inst.getOperand(2).getImm();
5246 const signed Size = Inst.getOperand(3).getImm();
5247 if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
5248 return Match_RequiresPosSizeRange0_32;
5249 return Match_Success;
5250 }
5251 case Mips::DINSM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005252 case Mips::DINSU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005253 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5254 "Operands must be immediates for dinsm/dinsu!");
5255 const signed Pos = Inst.getOperand(2).getImm();
5256 const signed Size = Inst.getOperand(3).getImm();
5257 if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
5258 return Match_RequiresPosSizeRange33_64;
5259 return Match_Success;
5260 }
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005261 case Mips::DEXT: {
Simon Dardis55e44672017-09-14 17:27:53 +00005262 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5263 "Operands must be immediates for DEXTM!");
5264 const signed Pos = Inst.getOperand(2).getImm();
5265 const signed Size = Inst.getOperand(3).getImm();
5266 if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
5267 return Match_RequiresPosSizeUImm6;
5268 return Match_Success;
5269 }
5270 case Mips::DEXTM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005271 case Mips::DEXTU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005272 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5273 "Operands must be immediates for dextm/dextu!");
5274 const signed Pos = Inst.getOperand(2).getImm();
5275 const signed Size = Inst.getOperand(3).getImm();
5276 if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
5277 return Match_RequiresPosSizeRange33_64;
5278 return Match_Success;
5279 }
Petar Jovanovic3408caf2018-03-14 14:13:31 +00005280 case Mips::CRC32B: case Mips::CRC32CB:
5281 case Mips::CRC32H: case Mips::CRC32CH:
5282 case Mips::CRC32W: case Mips::CRC32CW:
5283 case Mips::CRC32D: case Mips::CRC32CD:
5284 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())
5285 return Match_RequiresSameSrcAndDst;
5286 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005287 }
Simon Dardis730fdb72017-01-16 13:55:58 +00005288
5289 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
5290 if ((TSFlags & MipsII::HasFCCRegOperand) &&
5291 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
5292 return Match_NoFCCRegisterForCurrentISA;
5293
5294 return Match_Success;
5295
Matheus Almeida595fcab2014-06-11 15:05:56 +00005296}
5297
Daniel Sanders52da7af2015-11-06 12:11:03 +00005298static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
5299 uint64_t ErrorInfo) {
5300 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
5301 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
5302 if (ErrorLoc == SMLoc())
5303 return Loc;
5304 return ErrorLoc;
5305 }
5306 return Loc;
5307}
5308
David Blaikie960ea3f2014-06-08 16:18:35 +00005309bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5310 OperandVector &Operands,
5311 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005312 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005313 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005314 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005315 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005316 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005317
5318 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005319 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005320 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005321 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005322 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005323 case Match_MissingFeature:
5324 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5325 return true;
5326 case Match_InvalidOperand: {
5327 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005328 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005329 if (ErrorInfo >= Operands.size())
5330 return Error(IDLoc, "too few operands for instruction");
5331
Daniel Sanders52da7af2015-11-06 12:11:03 +00005332 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005333 if (ErrorLoc == SMLoc())
5334 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005335 }
5336
5337 return Error(ErrorLoc, "invalid operand for instruction");
5338 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005339 case Match_NonZeroOperandForSync:
Simon Atanasyan478220f2018-05-24 07:36:00 +00005340 return Error(IDLoc,
5341 "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Simon Dardis52ae4f02018-03-07 11:39:48 +00005342 case Match_NonZeroOperandForMTCX:
5343 return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005344 case Match_MnemonicFail:
5345 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005346 case Match_RequiresDifferentSrcAndDst:
5347 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005348 case Match_RequiresDifferentOperands:
5349 return Error(IDLoc, "registers must be different");
5350 case Match_RequiresNoZeroRegister:
5351 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005352 case Match_RequiresSameSrcAndDst:
5353 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005354 case Match_NoFCCRegisterForCurrentISA:
5355 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5356 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005357 case Match_Immz:
5358 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005359 case Match_UImm1_0:
5360 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5361 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005362 case Match_UImm2_0:
5363 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5364 "expected 2-bit unsigned immediate");
5365 case Match_UImm2_1:
5366 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5367 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005368 case Match_UImm3_0:
5369 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5370 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005371 case Match_UImm4_0:
5372 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5373 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005374 case Match_SImm4_0:
5375 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5376 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005377 case Match_UImm5_0:
5378 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5379 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005380 case Match_SImm5_0:
5381 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5382 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005383 case Match_UImm5_1:
5384 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5385 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005386 case Match_UImm5_32:
5387 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5388 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005389 case Match_UImm5_33:
5390 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5391 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005392 case Match_UImm5_0_Report_UImm6:
5393 // This is used on UImm5 operands that have a corresponding UImm5_32
5394 // operand to avoid confusing the user.
5395 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5396 "expected 6-bit unsigned immediate");
5397 case Match_UImm5_Lsl2:
5398 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5399 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005400 case Match_UImmRange2_64:
5401 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5402 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005403 case Match_UImm6_0:
5404 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5405 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005406 case Match_UImm6_Lsl2:
5407 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5408 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005409 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005410 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5411 "expected 6-bit signed immediate");
5412 case Match_UImm7_0:
5413 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5414 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005415 case Match_UImm7_N1:
5416 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5417 "expected immediate in range -1 .. 126");
5418 case Match_SImm7_Lsl2:
5419 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5420 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005421 case Match_UImm8_0:
5422 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5423 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005424 case Match_UImm10_0:
5425 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5426 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005427 case Match_SImm10_0:
5428 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5429 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005430 case Match_SImm11_0:
5431 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5432 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005433 case Match_UImm16:
5434 case Match_UImm16_Relaxed:
Petar Jovanovice4dacb72017-09-12 21:43:33 +00005435 case Match_UImm16_AltRelaxed:
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005436 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5437 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005438 case Match_SImm16:
5439 case Match_SImm16_Relaxed:
5440 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5441 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005442 case Match_SImm19_Lsl2:
5443 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5444 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005445 case Match_UImm20_0:
5446 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5447 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005448 case Match_UImm26_0:
5449 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5450 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005451 case Match_SImm32:
5452 case Match_SImm32_Relaxed:
5453 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5454 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005455 case Match_UImm32_Coerced:
5456 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5457 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005458 case Match_MemSImm9:
5459 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5460 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005461 case Match_MemSImm10:
5462 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5463 "expected memory with 10-bit signed offset");
5464 case Match_MemSImm10Lsl1:
5465 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5466 "expected memory with 11-bit signed offset and multiple of 2");
5467 case Match_MemSImm10Lsl2:
5468 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5469 "expected memory with 12-bit signed offset and multiple of 4");
5470 case Match_MemSImm10Lsl3:
5471 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5472 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005473 case Match_MemSImm11:
5474 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5475 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005476 case Match_MemSImm12:
5477 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5478 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005479 case Match_MemSImm16:
5480 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5481 "expected memory with 16-bit signed offset");
Simon Atanasyand4d892f2018-04-26 19:55:28 +00005482 case Match_MemSImmPtr:
5483 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5484 "expected memory with 32-bit signed offset");
Simon Dardis6f83ae32017-09-14 15:17:50 +00005485 case Match_RequiresPosSizeRange0_32: {
5486 SMLoc ErrorStart = Operands[3]->getStartLoc();
5487 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5488 return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
5489 SMRange(ErrorStart, ErrorEnd));
5490 }
Simon Dardis55e44672017-09-14 17:27:53 +00005491 case Match_RequiresPosSizeUImm6: {
5492 SMLoc ErrorStart = Operands[3]->getStartLoc();
5493 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5494 return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
5495 SMRange(ErrorStart, ErrorEnd));
5496 }
Simon Dardis6f83ae32017-09-14 15:17:50 +00005497 case Match_RequiresPosSizeRange33_64: {
5498 SMLoc ErrorStart = Operands[3]->getStartLoc();
5499 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5500 return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
5501 SMRange(ErrorStart, ErrorEnd));
5502 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005503 }
Craig Topper589ceee2015-01-03 08:16:34 +00005504
5505 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005506}
5507
Toma Tabacud9d344b2015-04-27 14:05:04 +00005508void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5509 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5510 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5511 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005512}
5513
Toma Tabacu81496c12015-05-20 08:54:45 +00005514void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5515 if (!AssemblerOptions.back()->isMacro())
5516 Warning(Loc, "macro instruction expanded into multiple instructions");
5517}
5518
Simon Dardis6a319922018-05-25 16:15:48 +00005519void MipsAsmParser::ConvertXWPOperands(MCInst &Inst,
5520 const OperandVector &Operands) {
5521 assert(
5522 (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) &&
5523 "Unexpected instruction!");
5524 ((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, 1);
5525 int NextReg = nextReg(((MipsOperand &)*Operands[1]).getGPR32Reg());
5526 Inst.addOperand(MCOperand::createReg(NextReg));
5527 ((MipsOperand &)*Operands[2]).addMemOperands(Inst, 2);
5528}
5529
Daniel Sandersef638fe2014-10-03 15:37:37 +00005530void
5531MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5532 SMRange Range, bool ShowColors) {
5533 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005534 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005535 ShowColors);
5536}
5537
Jack Carter1ac53222013-02-20 23:11:17 +00005538int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005539 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005540
Vladimir Medic4c299852013-11-06 11:27:05 +00005541 CC = StringSwitch<unsigned>(Name)
5542 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005543 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005544 .Case("a0", 4)
5545 .Case("a1", 5)
5546 .Case("a2", 6)
5547 .Case("a3", 7)
5548 .Case("v0", 2)
5549 .Case("v1", 3)
5550 .Case("s0", 16)
5551 .Case("s1", 17)
5552 .Case("s2", 18)
5553 .Case("s3", 19)
5554 .Case("s4", 20)
5555 .Case("s5", 21)
5556 .Case("s6", 22)
5557 .Case("s7", 23)
5558 .Case("k0", 26)
5559 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005560 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005561 .Case("sp", 29)
5562 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005563 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005564 .Case("ra", 31)
5565 .Case("t0", 8)
5566 .Case("t1", 9)
5567 .Case("t2", 10)
5568 .Case("t3", 11)
5569 .Case("t4", 12)
5570 .Case("t5", 13)
5571 .Case("t6", 14)
5572 .Case("t7", 15)
5573 .Case("t8", 24)
5574 .Case("t9", 25)
5575 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005576
Toma Tabacufda445c2014-09-15 15:33:01 +00005577 if (!(isABI_N32() || isABI_N64()))
5578 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005579
Daniel Sandersef638fe2014-10-03 15:37:37 +00005580 if (12 <= CC && CC <= 15) {
5581 // Name is one of t4-t7
5582 AsmToken RegTok = getLexer().peekTok();
5583 SMRange RegRange = RegTok.getLocRange();
5584
5585 StringRef FixedName = StringSwitch<StringRef>(Name)
5586 .Case("t4", "t0")
5587 .Case("t5", "t1")
5588 .Case("t6", "t2")
5589 .Case("t7", "t3")
5590 .Default("");
5591 assert(FixedName != "" && "Register name is not one of t4-t7.");
5592
5593 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5594 "Did you mean $" + FixedName + "?", RegRange);
5595 }
5596
Toma Tabacufda445c2014-09-15 15:33:01 +00005597 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5598 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5599 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5600 if (8 <= CC && CC <= 11)
5601 CC += 4;
5602
5603 if (CC == -1)
5604 CC = StringSwitch<unsigned>(Name)
5605 .Case("a4", 8)
5606 .Case("a5", 9)
5607 .Case("a6", 10)
5608 .Case("a7", 11)
5609 .Case("kt0", 26)
5610 .Case("kt1", 27)
5611 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005612
5613 return CC;
5614}
Jack Carterd0bd6422013-04-18 00:41:53 +00005615
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005616int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5617 int CC;
5618
5619 CC = StringSwitch<unsigned>(Name)
5620 .Case("hwr_cpunum", 0)
5621 .Case("hwr_synci_step", 1)
5622 .Case("hwr_cc", 2)
5623 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005624 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005625 .Default(-1);
5626
5627 return CC;
5628}
5629
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005630int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005631 if (Name[0] == 'f') {
5632 StringRef NumString = Name.substr(1);
5633 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005634 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005635 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005636 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005637 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005638 return IntVal;
5639 }
5640 return -1;
5641}
Jack Cartera63b16a2012-09-07 00:23:42 +00005642
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005643int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005644 if (Name.startswith("fcc")) {
5645 StringRef NumString = Name.substr(3);
5646 unsigned IntVal;
5647 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005648 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005649 if (IntVal > 7) // There are only 8 fcc registers.
5650 return -1;
5651 return IntVal;
5652 }
5653 return -1;
5654}
5655
5656int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005657 if (Name.startswith("ac")) {
5658 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005659 unsigned IntVal;
5660 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005661 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005662 if (IntVal > 3) // There are only 3 acc registers.
5663 return -1;
5664 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005665 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005666 return -1;
5667}
Jack Carterd0bd6422013-04-18 00:41:53 +00005668
Jack Carter5dc8ac92013-09-25 23:50:44 +00005669int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5670 unsigned IntVal;
5671
5672 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5673 return -1;
5674
5675 if (IntVal > 31)
5676 return -1;
5677
5678 return IntVal;
5679}
5680
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005681int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5682 int CC;
5683
5684 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005685 .Case("msair", 0)
5686 .Case("msacsr", 1)
5687 .Case("msaaccess", 2)
5688 .Case("msasave", 3)
5689 .Case("msamodify", 4)
5690 .Case("msarequest", 5)
5691 .Case("msamap", 6)
5692 .Case("msaunmap", 7)
5693 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005694
5695 return CC;
5696}
5697
Simon Dardis3aa8a902017-02-06 12:43:46 +00005698bool MipsAsmParser::canUseATReg() {
5699 return AssemblerOptions.back()->getATRegIndex() != 0;
5700}
5701
Toma Tabacu89a712b2015-04-15 10:48:56 +00005702unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005703 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005704 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005705 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005706 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005707 return 0;
5708 }
5709 unsigned AT = getReg(
5710 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005711 return AT;
5712}
Jack Carter0b744b32012-10-04 02:29:46 +00005713
Jack Carterd0bd6422013-04-18 00:41:53 +00005714unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005715 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005716}
5717
Toma Tabacu13964452014-09-04 13:23:44 +00005718bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005719 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005720 LLVM_DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005721
Jack Carter30a59822012-10-04 04:03:53 +00005722 // Check if the current operand has a custom associated parser, if so, try to
5723 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005724 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5725 if (ResTy == MatchOperand_Success)
5726 return false;
5727 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5728 // there was a match, but an error occurred, in which case, just return that
5729 // the operand parsing failed.
5730 if (ResTy == MatchOperand_ParseFail)
5731 return true;
5732
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005733 LLVM_DEBUG(dbgs() << ".. Generic Parser\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005734
Jack Carterb4dbc172012-09-05 23:34:03 +00005735 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005736 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005737 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005738 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005739
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005740 // Almost all registers have been parsed by custom parsers. There is only
5741 // one exception to this. $zero (and it's alias $0) will reach this point
5742 // for div, divu, and similar instructions because it is not an operand
5743 // to the instruction definition but an explicit register. Special case
5744 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005745 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005746 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005747
Jack Carterd0bd6422013-04-18 00:41:53 +00005748 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005749 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005750 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005751 return true;
5752
Jack Carter873c7242013-01-12 01:03:14 +00005753 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005754 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005755 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005756 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005757 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005758
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005759 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005760 return false;
5761 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005762 default: {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005763 LLVM_DEBUG(dbgs() << ".. generic integer expression\n");
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005764
5765 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005766 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005767 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005768 return true;
5769
Jack Carter873c7242013-01-12 01:03:14 +00005770 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5771
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005772 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005773 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005774 }
Jack Carter0b744b32012-10-04 02:29:46 +00005775 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005776 return true;
5777}
5778
Jack Carterb5cf5902013-04-17 00:18:04 +00005779bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005780 switch (Expr->getKind()) {
5781 case MCExpr::Constant:
5782 return true;
5783 case MCExpr::SymbolRef:
5784 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
Simon Dardisc6be2252017-08-09 10:47:52 +00005785 case MCExpr::Binary: {
Simon Dardis02c9a3d2017-08-18 13:27:02 +00005786 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
Simon Dardisc6be2252017-08-09 10:47:52 +00005787 if (!isEvaluated(BE->getLHS()))
5788 return false;
5789 return isEvaluated(BE->getRHS());
5790 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005791 case MCExpr::Unary:
5792 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005793 case MCExpr::Target:
5794 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005795 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005796 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005797}
Jack Carterd0bd6422013-04-18 00:41:53 +00005798
Jack Carterb4dbc172012-09-05 23:34:03 +00005799bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5800 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005801 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005802 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005803 if (ResTy == MatchOperand_Success) {
5804 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005805 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005806 StartLoc = Operand.getStartLoc();
5807 EndLoc = Operand.getEndLoc();
5808
5809 // AFAIK, we only support numeric registers and named GPR's in CFI
5810 // directives.
5811 // Don't worry about eating tokens before failing. Using an unrecognised
5812 // register is a parse error.
5813 if (Operand.isGPRAsmReg()) {
5814 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005815 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005816 }
5817
5818 return (RegNo == (unsigned)-1);
5819 }
5820
5821 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005822 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005823}
5824
Jack Carterb5cf5902013-04-17 00:18:04 +00005825bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005826 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005827
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005828 if (isParenExpr)
5829 return getParser().parseParenExprOfDepth(0, Res, S);
5830 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005831}
5832
Alex Bradbury58eba092016-11-01 16:32:05 +00005833OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005834MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005835 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005836 LLVM_DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005837 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005838 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005839 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005840 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005841 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005842 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005843
Jack Carterb5cf5902013-04-17 00:18:04 +00005844 if (getLexer().getKind() == AsmToken::LParen) {
5845 Parser.Lex();
5846 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005847 }
5848
Jack Carterb5cf5902013-04-17 00:18:04 +00005849 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005850 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005851 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005852
Jack Carterd0bd6422013-04-18 00:41:53 +00005853 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005854 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005855 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005856 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005857 SMLoc E =
5858 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005859 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005860 return MatchOperand_Success;
5861 }
5862 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005863 SMLoc E =
5864 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005865
Jack Carterd0bd6422013-04-18 00:41:53 +00005866 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005867 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005868 auto Base = MipsOperand::createGPRReg(
5869 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005870 Operands.push_back(
5871 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005872 return MatchOperand_Success;
5873 }
Simon Dardis858915f2016-10-18 15:17:17 +00005874 MCBinaryExpr::Opcode Opcode;
5875 // GAS and LLVM treat comparison operators different. GAS will generate -1
5876 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5877 // highly unlikely to be found in a memory offset expression, we don't
5878 // handle them.
5879 switch (Tok.getKind()) {
5880 case AsmToken::Plus:
5881 Opcode = MCBinaryExpr::Add;
5882 Parser.Lex();
5883 break;
5884 case AsmToken::Minus:
5885 Opcode = MCBinaryExpr::Sub;
5886 Parser.Lex();
5887 break;
5888 case AsmToken::Star:
5889 Opcode = MCBinaryExpr::Mul;
5890 Parser.Lex();
5891 break;
5892 case AsmToken::Pipe:
5893 Opcode = MCBinaryExpr::Or;
5894 Parser.Lex();
5895 break;
5896 case AsmToken::Amp:
5897 Opcode = MCBinaryExpr::And;
5898 Parser.Lex();
5899 break;
5900 case AsmToken::LessLess:
5901 Opcode = MCBinaryExpr::Shl;
5902 Parser.Lex();
5903 break;
5904 case AsmToken::GreaterGreater:
5905 Opcode = MCBinaryExpr::LShr;
5906 Parser.Lex();
5907 break;
5908 case AsmToken::Caret:
5909 Opcode = MCBinaryExpr::Xor;
5910 Parser.Lex();
5911 break;
5912 case AsmToken::Slash:
5913 Opcode = MCBinaryExpr::Div;
5914 Parser.Lex();
5915 break;
5916 case AsmToken::Percent:
5917 Opcode = MCBinaryExpr::Mod;
5918 Parser.Lex();
5919 break;
5920 default:
5921 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5922 return MatchOperand_ParseFail;
5923 }
5924 const MCExpr * NextExpr;
5925 if (getParser().parseExpression(NextExpr))
5926 return MatchOperand_ParseFail;
5927 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005928 }
5929
Jack Carterd0bd6422013-04-18 00:41:53 +00005930 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005931 }
5932
Toma Tabacu13964452014-09-04 13:23:44 +00005933 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005934 if (Res != MatchOperand_Success)
5935 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005936
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005937 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005938 Error(Parser.getTok().getLoc(), "')' expected");
5939 return MatchOperand_ParseFail;
5940 }
5941
Jack Carter873c7242013-01-12 01:03:14 +00005942 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5943
Jack Carterd0bd6422013-04-18 00:41:53 +00005944 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005945
Craig Topper062a2ba2014-04-25 05:30:21 +00005946 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005947 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005948
Jack Carterd0bd6422013-04-18 00:41:53 +00005949 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005950 std::unique_ptr<MipsOperand> op(
5951 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005952 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005953 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005954 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005955 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005956 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5957 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005958 if (IdVal->evaluateAsAbsolute(Imm))
5959 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005960 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005961 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005962 getContext());
5963 }
5964
David Blaikie960ea3f2014-06-08 16:18:35 +00005965 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005966 return MatchOperand_Success;
5967}
5968
David Blaikie960ea3f2014-06-08 16:18:35 +00005969bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005970 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005971 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00005972 if (!Sym)
5973 return false;
5974
5975 SMLoc S = Parser.getTok().getLoc();
5976 if (Sym->isVariable()) {
5977 const MCExpr *Expr = Sym->getVariableValue();
Jack Carterd76b2372013-03-21 21:44:16 +00005978 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005979 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005980 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005981 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005982 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005983 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005984 if (ResTy == MatchOperand_Success) {
5985 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005986 return true;
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00005987 }
5988 if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005989 llvm_unreachable("Should never ParseFail");
Jack Carterd76b2372013-03-21 21:44:16 +00005990 }
Jack Carterd76b2372013-03-21 21:44:16 +00005991 }
Simon Atanasyan69301c92018-05-29 15:58:06 +00005992 } else if (Sym->isUnset()) {
5993 // If symbol is unset, it might be created in the `parseSetAssignment`
5994 // routine as an alias for a numeric register name.
5995 // Lookup in the aliases list.
5996 auto Entry = RegisterSets.find(Sym->getName());
5997 if (Entry != RegisterSets.end()) {
5998 OperandMatchResultTy ResTy =
5999 matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S);
6000 if (ResTy == MatchOperand_Success) {
6001 Parser.Lex();
6002 return true;
6003 }
6004 }
Jack Carterd76b2372013-03-21 21:44:16 +00006005 }
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00006006
Jack Carterd76b2372013-03-21 21:44:16 +00006007 return false;
6008}
Jack Carterd0bd6422013-04-18 00:41:53 +00006009
Alex Bradbury58eba092016-11-01 16:32:05 +00006010OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006011MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00006012 StringRef Identifier,
6013 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006014 int Index = matchCPURegisterName(Identifier);
6015 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006016 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006017 Index, Identifier, getContext().getRegisterInfo(), S,
6018 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006019 return MatchOperand_Success;
6020 }
6021
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00006022 Index = matchHWRegsRegisterName(Identifier);
6023 if (Index != -1) {
6024 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006025 Index, Identifier, getContext().getRegisterInfo(), S,
6026 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00006027 return MatchOperand_Success;
6028 }
6029
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006030 Index = matchFPURegisterName(Identifier);
6031 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006032 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006033 Index, Identifier, getContext().getRegisterInfo(), S,
6034 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006035 return MatchOperand_Success;
6036 }
6037
6038 Index = matchFCCRegisterName(Identifier);
6039 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006040 Operands.push_back(MipsOperand::createFCCReg(
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 = matchACRegisterName(Identifier);
6047 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006048 Operands.push_back(MipsOperand::createACCReg(
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 = matchMSA128RegisterName(Identifier);
6055 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006056 Operands.push_back(MipsOperand::createMSA128Reg(
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 = matchMSA128CtrlRegisterName(Identifier);
6063 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006064 Operands.push_back(MipsOperand::createMSACtrlReg(
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 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00006071}
6072
Alex Bradbury58eba092016-11-01 16:32:05 +00006073OperandMatchResultTy
Simon Atanasyan69301c92018-05-29 15:58:06 +00006074MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands,
6075 const AsmToken &Token, SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006076 if (Token.is(AsmToken::Identifier)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006077 LLVM_DEBUG(dbgs() << ".. identifier\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006078 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00006079 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00006080 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00006081 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006082 } else if (Token.is(AsmToken::Integer)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006083 LLVM_DEBUG(dbgs() << ".. integer\n");
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006084 int64_t RegNum = Token.getIntVal();
6085 if (RegNum < 0 || RegNum > 31) {
6086 // Show the error, but treat invalid register
6087 // number as a normal one to continue parsing
6088 // and catch other possible errors.
6089 Error(getLexer().getLoc(), "invalid register number");
6090 }
Toma Tabacu13964452014-09-04 13:23:44 +00006091 Operands.push_back(MipsOperand::createNumericReg(
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006092 RegNum, Token.getString(), getContext().getRegisterInfo(), S,
Daniel Sandersc5537422016-07-27 13:49:44 +00006093 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006094 return MatchOperand_Success;
6095 }
6096
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00006097 LLVM_DEBUG(dbgs() << Token.getKind() << "\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006098
6099 return MatchOperand_NoMatch;
6100}
6101
Alex Bradbury58eba092016-11-01 16:32:05 +00006102OperandMatchResultTy
Simon Atanasyan69301c92018-05-29 15:58:06 +00006103MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
6104 auto Token = getLexer().peekTok(false);
6105 return matchAnyRegisterWithoutDollar(Operands, Token, S);
6106}
6107
6108OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006109MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006110 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006111 LLVM_DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006112
6113 auto Token = Parser.getTok();
6114
6115 SMLoc S = Token.getLoc();
6116
6117 if (Token.isNot(AsmToken::Dollar)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006118 LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006119 if (Token.is(AsmToken::Identifier)) {
6120 if (searchSymbolAlias(Operands))
6121 return MatchOperand_Success;
6122 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006123 LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006124 return MatchOperand_NoMatch;
6125 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006126 LLVM_DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006127
Toma Tabacu13964452014-09-04 13:23:44 +00006128 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00006129 if (ResTy == MatchOperand_Success) {
6130 Parser.Lex(); // $
6131 Parser.Lex(); // identifier
6132 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006133 return ResTy;
6134}
6135
Alex Bradbury58eba092016-11-01 16:32:05 +00006136OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006137MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006138 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006139 LLVM_DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006140
6141 SMLoc S = getLexer().getLoc();
6142
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006143 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006144 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006145 if (ResTy != MatchOperand_NoMatch)
6146 return ResTy;
6147
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006148 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00006149 const MCExpr *Expr = nullptr;
6150 if (Parser.parseExpression(Expr)) {
6151 // We have no way of knowing if a symbol was consumed so we must ParseFail
6152 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006153 }
Daniel Sandersffd84362014-04-01 10:41:48 +00006154 Operands.push_back(
6155 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006156 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00006157}
6158
Alex Bradbury58eba092016-11-01 16:32:05 +00006159OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00006160MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006161 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00006162 const MCExpr *IdVal;
Simon Dardisa17a7b62017-10-10 13:34:45 +00006163 // If the first token is '$' we may have register operand. We have to reject
6164 // cases where it is not a register. Complicating the matter is that
6165 // register names are not reserved across all ABIs.
6166 // Peek past the dollar to see if it's a register name for this ABI.
Vladimir Medic2b953d02013-10-01 09:48:56 +00006167 SMLoc S = Parser.getTok().getLoc();
Simon Dardisa17a7b62017-10-10 13:34:45 +00006168 if (Parser.getTok().is(AsmToken::Dollar)) {
6169 return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
6170 ? MatchOperand_ParseFail
6171 : MatchOperand_NoMatch;
6172 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00006173 if (getParser().parseExpression(IdVal))
6174 return MatchOperand_ParseFail;
6175 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Simon Dardisa17a7b62017-10-10 13:34:45 +00006176 if (!MCE)
6177 return MatchOperand_NoMatch;
Vladimir Medic2b953d02013-10-01 09:48:56 +00006178 int64_t Val = MCE->getValue();
6179 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
6180 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00006181 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00006182 return MatchOperand_Success;
6183}
6184
Alex Bradbury58eba092016-11-01 16:32:05 +00006185OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006186MipsAsmParser::parseRegisterList(OperandVector &Operands) {
6187 MCAsmParser &Parser = getParser();
6188 SmallVector<unsigned, 10> Regs;
6189 unsigned RegNo;
6190 unsigned PrevReg = Mips::NoRegister;
6191 bool RegRange = false;
6192 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6193
6194 if (Parser.getTok().isNot(AsmToken::Dollar))
6195 return MatchOperand_ParseFail;
6196
6197 SMLoc S = Parser.getTok().getLoc();
6198 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
6199 SMLoc E = getLexer().getLoc();
6200 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
6201 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
6202 if (RegRange) {
6203 // Remove last register operand because registers from register range
6204 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006205 if ((isGP64bit() && RegNo == Mips::RA_64) ||
6206 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006207 Regs.push_back(RegNo);
6208 } else {
6209 unsigned TmpReg = PrevReg + 1;
6210 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006211 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
6212 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
6213 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006214 Error(E, "invalid register operand");
6215 return MatchOperand_ParseFail;
6216 }
6217
6218 PrevReg = TmpReg;
6219 Regs.push_back(TmpReg++);
6220 }
6221 }
6222
6223 RegRange = false;
6224 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006225 if ((PrevReg == Mips::NoRegister) &&
6226 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
6227 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006228 Error(E, "$16 or $31 expected");
6229 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006230 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
6231 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
6232 !isGP64bit()) ||
6233 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
6234 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
6235 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006236 Error(E, "invalid register operand");
6237 return MatchOperand_ParseFail;
6238 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006239 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
6240 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
6241 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006242 Error(E, "consecutive register numbers expected");
6243 return MatchOperand_ParseFail;
6244 }
6245
6246 Regs.push_back(RegNo);
6247 }
6248
6249 if (Parser.getTok().is(AsmToken::Minus))
6250 RegRange = true;
6251
6252 if (!Parser.getTok().isNot(AsmToken::Minus) &&
6253 !Parser.getTok().isNot(AsmToken::Comma)) {
6254 Error(E, "',' or '-' expected");
6255 return MatchOperand_ParseFail;
6256 }
6257
6258 Lex(); // Consume comma or minus
6259 if (Parser.getTok().isNot(AsmToken::Dollar))
6260 break;
6261
6262 PrevReg = RegNo;
6263 }
6264
6265 SMLoc E = Parser.getTok().getLoc();
6266 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6267 parseMemOperand(Operands);
6268 return MatchOperand_Success;
6269}
6270
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006271/// Sometimes (i.e. load/stores) the operand may be followed immediately by
6272/// either this.
6273/// ::= '(', register, ')'
6274/// handle it before we iterate so we don't get tripped up by the lack of
6275/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006276bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006277 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006278 if (getLexer().is(AsmToken::LParen)) {
6279 Operands.push_back(
6280 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
6281 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006282 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006283 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006284 return Error(Loc, "unexpected token in argument list");
6285 }
6286 if (Parser.getTok().isNot(AsmToken::RParen)) {
6287 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006288 return Error(Loc, "unexpected token, expected ')'");
6289 }
6290 Operands.push_back(
6291 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
6292 Parser.Lex();
6293 }
6294 return false;
6295}
6296
6297/// Sometimes (i.e. in MSA) the operand may be followed immediately by
6298/// either one of these.
6299/// ::= '[', register, ']'
6300/// ::= '[', integer, ']'
6301/// handle it before we iterate so we don't get tripped up by the lack of
6302/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006303bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00006304 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006305 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006306 if (getLexer().is(AsmToken::LBrac)) {
6307 Operands.push_back(
6308 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
6309 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006310 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006311 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006312 return Error(Loc, "unexpected token in argument list");
6313 }
6314 if (Parser.getTok().isNot(AsmToken::RBrac)) {
6315 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006316 return Error(Loc, "unexpected token, expected ']'");
6317 }
6318 Operands.push_back(
6319 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
6320 Parser.Lex();
6321 }
6322 return false;
6323}
6324
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00006325static std::string MipsMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
Simon Atanasyanc49da2e2018-09-13 08:38:03 +00006326 unsigned VariantID = 0);
6327
David Blaikie960ea3f2014-06-08 16:18:35 +00006328bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6329 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006330 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006331 LLVM_DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006332
6333 // We have reached first instruction, module directive are now forbidden.
6334 getTargetStreamer().forbidModuleDirective();
6335
Vladimir Medic74593e62013-07-17 15:00:42 +00006336 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006337 if (!mnemonicIsValid(Name, 0)) {
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00006338 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
Simon Atanasyanc49da2e2018-09-13 08:38:03 +00006339 std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS);
6340 return Error(NameLoc, "unknown instruction" + Suggestion);
Vladimir Medic74593e62013-07-17 15:00:42 +00006341 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006342 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006343 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006344
6345 // Read the remaining operands.
6346 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6347 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006348 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006349 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006350 return Error(Loc, "unexpected token in argument list");
6351 }
Toma Tabacu13964452014-09-04 13:23:44 +00006352 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006353 return true;
6354 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006355
Jack Carterd0bd6422013-04-18 00:41:53 +00006356 while (getLexer().is(AsmToken::Comma)) {
6357 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006358 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006359 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006360 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006361 return Error(Loc, "unexpected token in argument list");
6362 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006363 // Parse bracket and parenthesis suffixes before we iterate
6364 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006365 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006366 return true;
6367 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006368 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006369 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006370 }
6371 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006372 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6373 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006374 return Error(Loc, "unexpected token in argument list");
6375 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006376 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006377 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006378}
6379
Nirav Dave996fc132016-05-05 14:15:46 +00006380// FIXME: Given that these have the same name, these should both be
6381// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006382bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006383 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006384 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006385}
6386
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006387bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006388 return Error(Loc, ErrorMsg);
6389}
6390
Jack Carter0b744b32012-10-04 02:29:46 +00006391bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006392 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006393 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006394
6395 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006396 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006397
6398 Parser.Lex(); // Eat "noat".
6399
Jack Carterd0bd6422013-04-18 00:41:53 +00006400 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006401 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006402 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006403 return false;
6404 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006405
6406 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006407 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006408 return false;
6409}
Jack Carterd0bd6422013-04-18 00:41:53 +00006410
Jack Carter0b744b32012-10-04 02:29:46 +00006411bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006412 // Line can be: ".set at", which sets $at to $1
6413 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006414 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006415 Parser.Lex(); // Eat "at".
6416
Jack Carter0b744b32012-10-04 02:29:46 +00006417 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006418 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006419 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006420
6421 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006422 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006423 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006424 }
6425
6426 if (getLexer().isNot(AsmToken::Equal)) {
6427 reportParseError("unexpected token, expected equals sign");
6428 return false;
6429 }
6430 Parser.Lex(); // Eat "=".
6431
6432 if (getLexer().isNot(AsmToken::Dollar)) {
6433 if (getLexer().is(AsmToken::EndOfStatement)) {
6434 reportParseError("no register specified");
6435 return false;
6436 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006437 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006438 return false;
6439 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006440 }
6441 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006442
Toma Tabacu16a74492015-02-13 10:30:57 +00006443 // Find out what "reg" is.
6444 unsigned AtRegNo;
6445 const AsmToken &Reg = Parser.getTok();
6446 if (Reg.is(AsmToken::Identifier)) {
6447 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6448 } else if (Reg.is(AsmToken::Integer)) {
6449 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006450 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006451 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006452 return false;
6453 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006454
6455 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006456 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006457 reportParseError("invalid register");
6458 return false;
6459 }
6460 Parser.Lex(); // Eat "reg".
6461
6462 // If this is not the end of the statement, report an error.
6463 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6464 reportParseError("unexpected token, expected end of statement");
6465 return false;
6466 }
6467
6468 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6469
6470 Parser.Lex(); // Consume the EndOfStatement.
6471 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006472}
6473
6474bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006475 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006476 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006477 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006478 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006479 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006480 return false;
6481 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006482 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006483 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006484 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006485 return false;
6486}
6487
6488bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006489 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006490 Parser.Lex();
6491 // If this is not the end of the statement, report an error.
6492 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006493 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006494 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006495 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006496 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006497 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006498 Parser.Lex(); // Consume the EndOfStatement.
6499 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006500}
6501
6502bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006503 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006504 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006505 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006506 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006507 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006508 return false;
6509 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006510 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006511 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006512 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006513 return false;
6514}
6515
6516bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006517 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006518 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006519 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006520 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006521 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006522 return false;
6523 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006524 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006525 reportParseError("`noreorder' must be set before `nomacro'");
6526 return false;
6527 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006528 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006529 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006530 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006531 return false;
6532}
Jack Carterd76b2372013-03-21 21:44:16 +00006533
Daniel Sanders44934432014-08-07 12:03:36 +00006534bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006535 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006536 Parser.Lex();
6537
6538 // If this is not the end of the statement, report an error.
6539 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006540 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006541
6542 setFeatureBits(Mips::FeatureMSA, "msa");
6543 getTargetStreamer().emitDirectiveSetMsa();
6544 return false;
6545}
6546
6547bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006548 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006549 Parser.Lex();
6550
6551 // If this is not the end of the statement, report an error.
6552 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006553 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006554
6555 clearFeatureBits(Mips::FeatureMSA, "msa");
6556 getTargetStreamer().emitDirectiveSetNoMsa();
6557 return false;
6558}
6559
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006560bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006561 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006562 Parser.Lex(); // Eat "nodsp".
6563
6564 // If this is not the end of the statement, report an error.
6565 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6566 reportParseError("unexpected token, expected end of statement");
6567 return false;
6568 }
6569
6570 clearFeatureBits(Mips::FeatureDSP, "dsp");
6571 getTargetStreamer().emitDirectiveSetNoDsp();
6572 return false;
6573}
6574
Toma Tabacucc2502d2014-11-04 17:18:07 +00006575bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006576 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006577 Parser.Lex(); // Eat "mips16".
6578
Jack Carter39536722014-01-22 23:08:42 +00006579 // If this is not the end of the statement, report an error.
6580 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006581 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006582 return false;
6583 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006584
6585 setFeatureBits(Mips::FeatureMips16, "mips16");
6586 getTargetStreamer().emitDirectiveSetMips16();
6587 Parser.Lex(); // Consume the EndOfStatement.
6588 return false;
6589}
6590
6591bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006592 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006593 Parser.Lex(); // Eat "nomips16".
6594
6595 // If this is not the end of the statement, report an error.
6596 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6597 reportParseError("unexpected token, expected end of statement");
6598 return false;
6599 }
6600
6601 clearFeatureBits(Mips::FeatureMips16, "mips16");
6602 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006603 Parser.Lex(); // Consume the EndOfStatement.
6604 return false;
6605}
6606
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006607bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006608 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006609 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006610 // Line can be: .set fp=32
6611 // .set fp=xx
6612 // .set fp=64
6613 Parser.Lex(); // Eat fp token
6614 AsmToken Tok = Parser.getTok();
6615 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006616 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006617 return false;
6618 }
6619 Parser.Lex(); // Eat '=' token.
6620 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006621
6622 if (!parseFpABIValue(FpAbiVal, ".set"))
6623 return false;
6624
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006625 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006626 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006627 return false;
6628 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006629 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006630 Parser.Lex(); // Consume the EndOfStatement.
6631 return false;
6632}
6633
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006634bool MipsAsmParser::parseSetOddSPRegDirective() {
6635 MCAsmParser &Parser = getParser();
6636
6637 Parser.Lex(); // Eat "oddspreg".
6638 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6639 reportParseError("unexpected token, expected end of statement");
6640 return false;
6641 }
6642
6643 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6644 getTargetStreamer().emitDirectiveSetOddSPReg();
6645 return false;
6646}
6647
6648bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6649 MCAsmParser &Parser = getParser();
6650
6651 Parser.Lex(); // Eat "nooddspreg".
6652 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6653 reportParseError("unexpected token, expected end of statement");
6654 return false;
6655 }
6656
6657 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6658 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6659 return false;
6660}
6661
Simon Dardis805f1e02017-07-11 21:28:36 +00006662bool MipsAsmParser::parseSetMtDirective() {
6663 MCAsmParser &Parser = getParser();
6664 Parser.Lex(); // Eat "mt".
6665
6666 // If this is not the end of the statement, report an error.
6667 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6668 reportParseError("unexpected token, expected end of statement");
6669 return false;
6670 }
6671
6672 setFeatureBits(Mips::FeatureMT, "mt");
6673 getTargetStreamer().emitDirectiveSetMt();
6674 Parser.Lex(); // Consume the EndOfStatement.
6675 return false;
6676}
6677
6678bool MipsAsmParser::parseSetNoMtDirective() {
6679 MCAsmParser &Parser = getParser();
6680 Parser.Lex(); // Eat "nomt".
6681
6682 // If this is not the end of the statement, report an error.
6683 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6684 reportParseError("unexpected token, expected end of statement");
6685 return false;
6686 }
6687
6688 clearFeatureBits(Mips::FeatureMT, "mt");
6689
6690 getTargetStreamer().emitDirectiveSetNoMt();
6691 Parser.Lex(); // Consume the EndOfStatement.
6692 return false;
6693}
6694
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006695bool MipsAsmParser::parseSetNoCRCDirective() {
6696 MCAsmParser &Parser = getParser();
6697 Parser.Lex(); // Eat "nocrc".
6698
6699 // If this is not the end of the statement, report an error.
6700 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6701 reportParseError("unexpected token, expected end of statement");
6702 return false;
6703 }
6704
6705 clearFeatureBits(Mips::FeatureCRC, "crc");
6706
6707 getTargetStreamer().emitDirectiveSetNoCRC();
6708 Parser.Lex(); // Consume the EndOfStatement.
6709 return false;
6710}
6711
Petar Jovanovicd4349f32018-04-27 09:12:08 +00006712bool MipsAsmParser::parseSetNoVirtDirective() {
6713 MCAsmParser &Parser = getParser();
6714 Parser.Lex(); // Eat "novirt".
6715
6716 // If this is not the end of the statement, report an error.
6717 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6718 reportParseError("unexpected token, expected end of statement");
6719 return false;
6720 }
6721
6722 clearFeatureBits(Mips::FeatureVirt, "virt");
6723
6724 getTargetStreamer().emitDirectiveSetNoVirt();
6725 Parser.Lex(); // Consume the EndOfStatement.
6726 return false;
6727}
6728
Petar Jovanovicdaf51692018-05-17 16:30:32 +00006729bool MipsAsmParser::parseSetNoGINVDirective() {
6730 MCAsmParser &Parser = getParser();
6731 Parser.Lex(); // Eat "noginv".
6732
6733 // If this is not the end of the statement, report an error.
6734 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6735 reportParseError("unexpected token, expected end of statement");
6736 return false;
6737 }
6738
6739 clearFeatureBits(Mips::FeatureGINV, "ginv");
6740
6741 getTargetStreamer().emitDirectiveSetNoGINV();
6742 Parser.Lex(); // Consume the EndOfStatement.
6743 return false;
6744}
6745
Toma Tabacu9db22db2014-09-09 10:15:38 +00006746bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006747 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006748 SMLoc Loc = getLexer().getLoc();
6749
6750 Parser.Lex();
6751 if (getLexer().isNot(AsmToken::EndOfStatement))
6752 return reportParseError("unexpected token, expected end of statement");
6753
6754 // Always keep an element on the options "stack" to prevent the user
6755 // from changing the initial options. This is how we remember them.
6756 if (AssemblerOptions.size() == 2)
6757 return reportParseError(Loc, ".set pop with no .set push");
6758
Akira Hatanakab11ef082015-11-14 06:35:56 +00006759 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006760 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006761 setAvailableFeatures(
6762 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6763 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006764
6765 getTargetStreamer().emitDirectiveSetPop();
6766 return false;
6767}
6768
6769bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006770 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006771 Parser.Lex();
6772 if (getLexer().isNot(AsmToken::EndOfStatement))
6773 return reportParseError("unexpected token, expected end of statement");
6774
6775 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006776 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006777 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006778
6779 getTargetStreamer().emitDirectiveSetPush();
6780 return false;
6781}
6782
Toma Tabacu29696502015-06-02 09:48:04 +00006783bool MipsAsmParser::parseSetSoftFloatDirective() {
6784 MCAsmParser &Parser = getParser();
6785 Parser.Lex();
6786 if (getLexer().isNot(AsmToken::EndOfStatement))
6787 return reportParseError("unexpected token, expected end of statement");
6788
6789 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6790 getTargetStreamer().emitDirectiveSetSoftFloat();
6791 return false;
6792}
6793
6794bool MipsAsmParser::parseSetHardFloatDirective() {
6795 MCAsmParser &Parser = getParser();
6796 Parser.Lex();
6797 if (getLexer().isNot(AsmToken::EndOfStatement))
6798 return reportParseError("unexpected token, expected end of statement");
6799
6800 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6801 getTargetStreamer().emitDirectiveSetHardFloat();
6802 return false;
6803}
6804
Jack Carterd76b2372013-03-21 21:44:16 +00006805bool MipsAsmParser::parseSetAssignment() {
6806 StringRef Name;
Rafael Espindola961d4692014-11-11 05:18:41 +00006807 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006808
6809 if (Parser.parseIdentifier(Name))
Simon Atanasyan3535cb12018-05-29 09:51:22 +00006810 return reportParseError("expected identifier after .set");
Jack Carterd76b2372013-03-21 21:44:16 +00006811
6812 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006813 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006814 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006815
Simon Atanasyan69301c92018-05-29 15:58:06 +00006816 if (getLexer().is(AsmToken::Dollar) &&
6817 getLexer().peekTok().is(AsmToken::Integer)) {
6818 // Parse assignment of a numeric register:
6819 // .set r1,$1
6820 Parser.Lex(); // Eat $.
6821 RegisterSets[Name] = Parser.getTok();
6822 Parser.Lex(); // Eat identifier.
6823 getContext().getOrCreateSymbol(Name);
Simon Atanasyanaf40d432019-03-19 15:15:35 +00006824 return false;
Simon Atanasyan69301c92018-05-29 15:58:06 +00006825 }
Jack Carterd76b2372013-03-21 21:44:16 +00006826
Simon Atanasyanaf40d432019-03-19 15:15:35 +00006827 MCSymbol *Sym;
6828 const MCExpr *Value;
6829 if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true,
6830 Parser, Sym, Value))
6831 return true;
6832 Sym->setVariableValue(Value);
6833
Jack Carterd76b2372013-03-21 21:44:16 +00006834 return false;
6835}
Jack Carterd0bd6422013-04-18 00:41:53 +00006836
Toma Tabacu26647792014-09-09 12:52:14 +00006837bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006838 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006839 Parser.Lex();
6840 if (getLexer().isNot(AsmToken::EndOfStatement))
6841 return reportParseError("unexpected token, expected end of statement");
6842
6843 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006844 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006845 setAvailableFeatures(
6846 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6847 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006848 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6849
6850 getTargetStreamer().emitDirectiveSetMips0();
6851 return false;
6852}
6853
Toma Tabacu85618b32014-08-19 14:22:52 +00006854bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006855 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006856 Parser.Lex();
6857 if (getLexer().isNot(AsmToken::Equal))
6858 return reportParseError("unexpected token, expected equals sign");
6859
6860 Parser.Lex();
6861 StringRef Arch;
6862 if (Parser.parseIdentifier(Arch))
6863 return reportParseError("expected arch identifier");
6864
6865 StringRef ArchFeatureName =
6866 StringSwitch<StringRef>(Arch)
6867 .Case("mips1", "mips1")
6868 .Case("mips2", "mips2")
6869 .Case("mips3", "mips3")
6870 .Case("mips4", "mips4")
6871 .Case("mips5", "mips5")
6872 .Case("mips32", "mips32")
6873 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006874 .Case("mips32r3", "mips32r3")
6875 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006876 .Case("mips32r6", "mips32r6")
6877 .Case("mips64", "mips64")
6878 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006879 .Case("mips64r3", "mips64r3")
6880 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006881 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006882 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006883 .Case("r4000", "mips3") // This is an implementation of Mips3.
6884 .Default("");
6885
6886 if (ArchFeatureName.empty())
6887 return reportParseError("unsupported architecture");
6888
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00006889 if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
6890 return reportParseError("mips64r6 does not support microMIPS");
6891
Toma Tabacu85618b32014-08-19 14:22:52 +00006892 selectArch(ArchFeatureName);
6893 getTargetStreamer().emitDirectiveSetArch(Arch);
6894 return false;
6895}
6896
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006897bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006898 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006899 Parser.Lex();
6900 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006901 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006902
Matheus Almeida2852af82014-04-22 10:15:54 +00006903 switch (Feature) {
6904 default:
6905 llvm_unreachable("Unimplemented feature");
6906 case Mips::FeatureDSP:
6907 setFeatureBits(Mips::FeatureDSP, "dsp");
6908 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006909 break;
Petar Jovanovic65f10242017-10-05 17:40:32 +00006910 case Mips::FeatureDSPR2:
6911 setFeatureBits(Mips::FeatureDSPR2, "dspr2");
6912 getTargetStreamer().emitDirectiveSetDspr2();
6913 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006914 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006915 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006916 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006917 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006918 case Mips::FeatureMips1:
6919 selectArch("mips1");
6920 getTargetStreamer().emitDirectiveSetMips1();
6921 break;
6922 case Mips::FeatureMips2:
6923 selectArch("mips2");
6924 getTargetStreamer().emitDirectiveSetMips2();
6925 break;
6926 case Mips::FeatureMips3:
6927 selectArch("mips3");
6928 getTargetStreamer().emitDirectiveSetMips3();
6929 break;
6930 case Mips::FeatureMips4:
6931 selectArch("mips4");
6932 getTargetStreamer().emitDirectiveSetMips4();
6933 break;
6934 case Mips::FeatureMips5:
6935 selectArch("mips5");
6936 getTargetStreamer().emitDirectiveSetMips5();
6937 break;
6938 case Mips::FeatureMips32:
6939 selectArch("mips32");
6940 getTargetStreamer().emitDirectiveSetMips32();
6941 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006942 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006943 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006944 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006945 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006946 case Mips::FeatureMips32r3:
6947 selectArch("mips32r3");
6948 getTargetStreamer().emitDirectiveSetMips32R3();
6949 break;
6950 case Mips::FeatureMips32r5:
6951 selectArch("mips32r5");
6952 getTargetStreamer().emitDirectiveSetMips32R5();
6953 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006954 case Mips::FeatureMips32r6:
6955 selectArch("mips32r6");
6956 getTargetStreamer().emitDirectiveSetMips32R6();
6957 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006958 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006959 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006960 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006961 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006962 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006963 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006964 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006965 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006966 case Mips::FeatureMips64r3:
6967 selectArch("mips64r3");
6968 getTargetStreamer().emitDirectiveSetMips64R3();
6969 break;
6970 case Mips::FeatureMips64r5:
6971 selectArch("mips64r5");
6972 getTargetStreamer().emitDirectiveSetMips64R5();
6973 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006974 case Mips::FeatureMips64r6:
6975 selectArch("mips64r6");
6976 getTargetStreamer().emitDirectiveSetMips64R6();
6977 break;
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006978 case Mips::FeatureCRC:
6979 setFeatureBits(Mips::FeatureCRC, "crc");
6980 getTargetStreamer().emitDirectiveSetCRC();
6981 break;
Petar Jovanovicd4349f32018-04-27 09:12:08 +00006982 case Mips::FeatureVirt:
6983 setFeatureBits(Mips::FeatureVirt, "virt");
6984 getTargetStreamer().emitDirectiveSetVirt();
6985 break;
Petar Jovanovicdaf51692018-05-17 16:30:32 +00006986 case Mips::FeatureGINV:
6987 setFeatureBits(Mips::FeatureGINV, "ginv");
6988 getTargetStreamer().emitDirectiveSetGINV();
6989 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006990 }
6991 return false;
6992}
6993
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006994bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006995 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006996 if (getLexer().isNot(AsmToken::Comma)) {
6997 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006998 return Error(Loc, ErrorStr);
6999 }
7000
Matheus Almeida2852af82014-04-22 10:15:54 +00007001 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007002 return true;
7003}
7004
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007005// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
7006// In this class, it is only used for .cprestore.
7007// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
7008// MipsTargetELFStreamer and MipsAsmParser.
7009bool MipsAsmParser::isPicAndNotNxxAbi() {
7010 return inPicMode() && !(isABI_N32() || isABI_N64());
7011}
7012
Toma Tabacuc4c202a2014-10-01 14:53:19 +00007013bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00007014 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00007015 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007016
Toma Tabacudde4c462014-11-06 10:02:45 +00007017 if (inMips16Mode()) {
7018 reportParseError(".cpload is not supported in Mips16 mode");
7019 return false;
7020 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007021
David Blaikie960ea3f2014-06-08 16:18:35 +00007022 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00007023 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007024 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7025 reportParseError("expected register containing function address");
7026 return false;
7027 }
7028
David Blaikie960ea3f2014-06-08 16:18:35 +00007029 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
7030 if (!RegOpnd.isGPRAsmReg()) {
7031 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007032 return false;
7033 }
7034
Toma Tabacudde4c462014-11-06 10:02:45 +00007035 // If this is not the end of the statement, report an error.
7036 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7037 reportParseError("unexpected token, expected end of statement");
7038 return false;
7039 }
7040
Toma Tabacuc4c202a2014-10-01 14:53:19 +00007041 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007042 return false;
7043}
7044
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007045bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
7046 MCAsmParser &Parser = getParser();
7047
7048 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
7049 // is used in non-PIC mode.
7050
7051 if (inMips16Mode()) {
7052 reportParseError(".cprestore is not supported in Mips16 mode");
7053 return false;
7054 }
7055
7056 // Get the stack offset value.
7057 const MCExpr *StackOffset;
7058 int64_t StackOffsetVal;
7059 if (Parser.parseExpression(StackOffset)) {
7060 reportParseError("expected stack offset value");
7061 return false;
7062 }
7063
7064 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
7065 reportParseError("stack offset is not an absolute expression");
7066 return false;
7067 }
7068
7069 if (StackOffsetVal < 0) {
7070 Warning(Loc, ".cprestore with negative stack offset has no effect");
7071 IsCpRestoreSet = false;
7072 } else {
7073 IsCpRestoreSet = true;
7074 CpRestoreOffset = StackOffsetVal;
7075 }
7076
7077 // If this is not the end of the statement, report an error.
7078 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7079 reportParseError("unexpected token, expected end of statement");
7080 return false;
7081 }
7082
Daniel Sandersdf8510d2016-05-11 12:48:19 +00007083 if (!getTargetStreamer().emitDirectiveCpRestore(
7084 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00007085 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007086 Parser.Lex(); // Consume the EndOfStatement.
7087 return false;
7088}
7089
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007090bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007091 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007092 unsigned FuncReg;
7093 unsigned Save;
7094 bool SaveIsReg = true;
7095
Matheus Almeida7e815762014-06-18 13:08:59 +00007096 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007097 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007098 if (ResTy == MatchOperand_NoMatch) {
7099 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00007100 return false;
7101 }
7102
7103 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7104 if (!FuncRegOpnd.isGPRAsmReg()) {
7105 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007106 return false;
7107 }
7108
7109 FuncReg = FuncRegOpnd.getGPR32Reg();
7110 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007111
Toma Tabacu65f10572014-09-16 15:00:52 +00007112 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007113 return true;
7114
Toma Tabacu13964452014-09-04 13:23:44 +00007115 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007116 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00007117 const MCExpr *OffsetExpr;
7118 int64_t OffsetVal;
7119 SMLoc ExprLoc = getLexer().getLoc();
7120
7121 if (Parser.parseExpression(OffsetExpr) ||
7122 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
7123 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00007124 return false;
7125 }
Daniel Sanders5d796282015-09-21 09:26:55 +00007126
7127 Save = OffsetVal;
7128 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00007129 } else {
7130 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7131 if (!SaveOpnd.isGPRAsmReg()) {
7132 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007133 return false;
7134 }
7135 Save = SaveOpnd.getGPR32Reg();
7136 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007137
Toma Tabacu65f10572014-09-16 15:00:52 +00007138 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007139 return true;
7140
Toma Tabacu8874eac2015-02-18 13:46:53 +00007141 const MCExpr *Expr;
7142 if (Parser.parseExpression(Expr)) {
7143 reportParseError("expected expression");
7144 return false;
7145 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007146
Toma Tabacu8874eac2015-02-18 13:46:53 +00007147 if (Expr->getKind() != MCExpr::SymbolRef) {
7148 reportParseError("expected symbol");
7149 return false;
7150 }
7151 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
7152
Daniel Sandersf173dda2015-09-22 10:50:09 +00007153 CpSaveLocation = Save;
7154 CpSaveLocationIsRegister = SaveIsReg;
7155
Toma Tabacu8874eac2015-02-18 13:46:53 +00007156 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
7157 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007158 return false;
7159}
7160
Daniel Sandersf173dda2015-09-22 10:50:09 +00007161bool MipsAsmParser::parseDirectiveCPReturn() {
7162 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
7163 CpSaveLocationIsRegister);
7164 return false;
7165}
7166
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007167bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007168 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007169 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7170 const AsmToken &Tok = Parser.getTok();
7171
7172 if (Tok.getString() == "2008") {
7173 Parser.Lex();
7174 getTargetStreamer().emitDirectiveNaN2008();
7175 return false;
7176 } else if (Tok.getString() == "legacy") {
7177 Parser.Lex();
7178 getTargetStreamer().emitDirectiveNaNLegacy();
7179 return false;
7180 }
7181 }
7182 // If we don't recognize the option passed to the .nan
7183 // directive (e.g. no option or unknown option), emit an error.
7184 reportParseError("invalid option in .nan directive");
7185 return false;
7186}
7187
Jack Carter0b744b32012-10-04 02:29:46 +00007188bool MipsAsmParser::parseDirectiveSet() {
Simon Atanasyand408ec42018-05-29 09:51:28 +00007189 const AsmToken &Tok = getParser().getTok();
7190 StringRef IdVal = Tok.getString();
7191 SMLoc Loc = Tok.getLoc();
Jack Carter0b744b32012-10-04 02:29:46 +00007192
Simon Atanasyand408ec42018-05-29 09:51:28 +00007193 if (IdVal == "noat")
Jack Carter0b744b32012-10-04 02:29:46 +00007194 return parseSetNoAtDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007195 if (IdVal == "at")
Jack Carter0b744b32012-10-04 02:29:46 +00007196 return parseSetAtDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007197 if (IdVal == "arch")
Toma Tabacu85618b32014-08-19 14:22:52 +00007198 return parseSetArchDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007199 if (IdVal == "bopt") {
7200 Warning(Loc, "'bopt' feature is unsupported");
Simon Dardisac9c30c2017-02-01 18:50:24 +00007201 getParser().Lex();
7202 return false;
Simon Atanasyand408ec42018-05-29 09:51:28 +00007203 }
7204 if (IdVal == "nobopt") {
Simon Dardisac9c30c2017-02-01 18:50:24 +00007205 // We're already running in nobopt mode, so nothing to do.
7206 getParser().Lex();
7207 return false;
Simon Atanasyand408ec42018-05-29 09:51:28 +00007208 }
7209 if (IdVal == "fp")
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007210 return parseSetFpDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007211 if (IdVal == "oddspreg")
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007212 return parseSetOddSPRegDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007213 if (IdVal == "nooddspreg")
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007214 return parseSetNoOddSPRegDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007215 if (IdVal == "pop")
Toma Tabacu9db22db2014-09-09 10:15:38 +00007216 return parseSetPopDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007217 if (IdVal == "push")
Toma Tabacu9db22db2014-09-09 10:15:38 +00007218 return parseSetPushDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007219 if (IdVal == "reorder")
Jack Carter0b744b32012-10-04 02:29:46 +00007220 return parseSetReorderDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007221 if (IdVal == "noreorder")
Jack Carter0b744b32012-10-04 02:29:46 +00007222 return parseSetNoReorderDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007223 if (IdVal == "macro")
Jack Carter0b744b32012-10-04 02:29:46 +00007224 return parseSetMacroDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007225 if (IdVal == "nomacro")
Jack Carter0b744b32012-10-04 02:29:46 +00007226 return parseSetNoMacroDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007227 if (IdVal == "mips16")
Toma Tabacucc2502d2014-11-04 17:18:07 +00007228 return parseSetMips16Directive();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007229 if (IdVal == "nomips16")
Jack Carter39536722014-01-22 23:08:42 +00007230 return parseSetNoMips16Directive();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007231 if (IdVal == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00007232 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007233 getTargetStreamer().emitDirectiveSetNoMicroMips();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007234 getParser().eatToEndOfStatement();
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007235 return false;
Simon Atanasyand408ec42018-05-29 09:51:28 +00007236 }
7237 if (IdVal == "micromips") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007238 if (hasMips64r6()) {
Simon Atanasyand408ec42018-05-29 09:51:28 +00007239 Error(Loc, ".set micromips directive is not supported with MIPS64R6");
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007240 return false;
7241 }
Matheus Almeida2852af82014-04-22 10:15:54 +00007242 return parseSetFeature(Mips::FeatureMicroMips);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007243 }
7244 if (IdVal == "mips0")
Toma Tabacu26647792014-09-09 12:52:14 +00007245 return parseSetMips0Directive();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007246 if (IdVal == "mips1")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007247 return parseSetFeature(Mips::FeatureMips1);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007248 if (IdVal == "mips2")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007249 return parseSetFeature(Mips::FeatureMips2);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007250 if (IdVal == "mips3")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007251 return parseSetFeature(Mips::FeatureMips3);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007252 if (IdVal == "mips4")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007253 return parseSetFeature(Mips::FeatureMips4);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007254 if (IdVal == "mips5")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007255 return parseSetFeature(Mips::FeatureMips5);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007256 if (IdVal == "mips32")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007257 return parseSetFeature(Mips::FeatureMips32);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007258 if (IdVal == "mips32r2")
Matheus Almeida2852af82014-04-22 10:15:54 +00007259 return parseSetFeature(Mips::FeatureMips32r2);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007260 if (IdVal == "mips32r3")
Daniel Sanders17793142015-02-18 16:24:50 +00007261 return parseSetFeature(Mips::FeatureMips32r3);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007262 if (IdVal == "mips32r5")
Daniel Sanders17793142015-02-18 16:24:50 +00007263 return parseSetFeature(Mips::FeatureMips32r5);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007264 if (IdVal == "mips32r6")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007265 return parseSetFeature(Mips::FeatureMips32r6);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007266 if (IdVal == "mips64")
Matheus Almeida2852af82014-04-22 10:15:54 +00007267 return parseSetFeature(Mips::FeatureMips64);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007268 if (IdVal == "mips64r2")
Matheus Almeida2852af82014-04-22 10:15:54 +00007269 return parseSetFeature(Mips::FeatureMips64r2);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007270 if (IdVal == "mips64r3")
Daniel Sanders17793142015-02-18 16:24:50 +00007271 return parseSetFeature(Mips::FeatureMips64r3);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007272 if (IdVal == "mips64r5")
Daniel Sanders17793142015-02-18 16:24:50 +00007273 return parseSetFeature(Mips::FeatureMips64r5);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007274 if (IdVal == "mips64r6") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007275 if (inMicroMipsMode()) {
Simon Atanasyand408ec42018-05-29 09:51:28 +00007276 Error(Loc, "MIPS64R6 is not supported with microMIPS");
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007277 return false;
7278 }
Daniel Sandersf0df2212014-08-04 12:20:00 +00007279 return parseSetFeature(Mips::FeatureMips64r6);
Jack Carter0b744b32012-10-04 02:29:46 +00007280 }
Simon Atanasyand408ec42018-05-29 09:51:28 +00007281 if (IdVal == "dsp")
7282 return parseSetFeature(Mips::FeatureDSP);
7283 if (IdVal == "dspr2")
7284 return parseSetFeature(Mips::FeatureDSPR2);
7285 if (IdVal == "nodsp")
7286 return parseSetNoDspDirective();
7287 if (IdVal == "msa")
7288 return parseSetMsaDirective();
7289 if (IdVal == "nomsa")
7290 return parseSetNoMsaDirective();
7291 if (IdVal == "mt")
7292 return parseSetMtDirective();
7293 if (IdVal == "nomt")
7294 return parseSetNoMtDirective();
7295 if (IdVal == "softfloat")
7296 return parseSetSoftFloatDirective();
7297 if (IdVal == "hardfloat")
7298 return parseSetHardFloatDirective();
7299 if (IdVal == "crc")
7300 return parseSetFeature(Mips::FeatureCRC);
7301 if (IdVal == "nocrc")
7302 return parseSetNoCRCDirective();
7303 if (IdVal == "virt")
7304 return parseSetFeature(Mips::FeatureVirt);
7305 if (IdVal == "novirt")
7306 return parseSetNoVirtDirective();
7307 if (IdVal == "ginv")
7308 return parseSetFeature(Mips::FeatureGINV);
7309 if (IdVal == "noginv")
7310 return parseSetNoGINVDirective();
Jack Carter07c818d2013-01-25 01:31:34 +00007311
Simon Atanasyand408ec42018-05-29 09:51:28 +00007312 // It is just an identifier, look for an assignment.
7313 return parseSetAssignment();
Jack Carter0b744b32012-10-04 02:29:46 +00007314}
7315
Vladimir Medic4c299852013-11-06 11:27:05 +00007316/// parseDirectiveGpWord
7317/// ::= .gpword local_sym
7318bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007319 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00007320 const MCExpr *Value;
7321 // EmitGPRel32Value requires an expression, so we are using base class
7322 // method to evaluate the expression.
7323 if (getParser().parseExpression(Value))
7324 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00007325 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00007326
Vladimir Medice10c1122013-11-13 13:18:04 +00007327 if (getLexer().isNot(AsmToken::EndOfStatement))
Fangrui Songf78650a2018-07-30 19:41:25 +00007328 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007329 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00007330 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00007331 return false;
7332}
7333
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007334/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00007335/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007336bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007337 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007338 const MCExpr *Value;
7339 // EmitGPRel64Value requires an expression, so we are using base class
7340 // method to evaluate the expression.
7341 if (getParser().parseExpression(Value))
7342 return true;
7343 getParser().getStreamer().EmitGPRel64Value(Value);
7344
7345 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007346 return Error(getLexer().getLoc(),
7347 "unexpected token, expected end of statement");
7348 Parser.Lex(); // Eat EndOfStatement token.
7349 return false;
7350}
7351
7352/// parseDirectiveDtpRelWord
7353/// ::= .dtprelword tls_sym
7354bool MipsAsmParser::parseDirectiveDtpRelWord() {
7355 MCAsmParser &Parser = getParser();
7356 const MCExpr *Value;
7357 // EmitDTPRel32Value requires an expression, so we are using base class
7358 // method to evaluate the expression.
7359 if (getParser().parseExpression(Value))
7360 return true;
7361 getParser().getStreamer().EmitDTPRel32Value(Value);
7362
7363 if (getLexer().isNot(AsmToken::EndOfStatement))
7364 return Error(getLexer().getLoc(),
7365 "unexpected token, expected end of statement");
7366 Parser.Lex(); // Eat EndOfStatement token.
7367 return false;
7368}
7369
7370/// parseDirectiveDtpRelDWord
7371/// ::= .dtpreldword tls_sym
7372bool MipsAsmParser::parseDirectiveDtpRelDWord() {
7373 MCAsmParser &Parser = getParser();
7374 const MCExpr *Value;
7375 // EmitDTPRel64Value requires an expression, so we are using base class
7376 // method to evaluate the expression.
7377 if (getParser().parseExpression(Value))
7378 return true;
7379 getParser().getStreamer().EmitDTPRel64Value(Value);
7380
7381 if (getLexer().isNot(AsmToken::EndOfStatement))
7382 return Error(getLexer().getLoc(),
7383 "unexpected token, expected end of statement");
7384 Parser.Lex(); // Eat EndOfStatement token.
7385 return false;
7386}
7387
7388/// parseDirectiveTpRelWord
7389/// ::= .tprelword tls_sym
7390bool MipsAsmParser::parseDirectiveTpRelWord() {
7391 MCAsmParser &Parser = getParser();
7392 const MCExpr *Value;
7393 // EmitTPRel32Value requires an expression, so we are using base class
7394 // method to evaluate the expression.
7395 if (getParser().parseExpression(Value))
7396 return true;
7397 getParser().getStreamer().EmitTPRel32Value(Value);
7398
7399 if (getLexer().isNot(AsmToken::EndOfStatement))
7400 return Error(getLexer().getLoc(),
7401 "unexpected token, expected end of statement");
7402 Parser.Lex(); // Eat EndOfStatement token.
7403 return false;
7404}
7405
7406/// parseDirectiveTpRelDWord
7407/// ::= .tpreldword tls_sym
7408bool MipsAsmParser::parseDirectiveTpRelDWord() {
7409 MCAsmParser &Parser = getParser();
7410 const MCExpr *Value;
7411 // EmitTPRel64Value requires an expression, so we are using base class
7412 // method to evaluate the expression.
7413 if (getParser().parseExpression(Value))
7414 return true;
7415 getParser().getStreamer().EmitTPRel64Value(Value);
7416
7417 if (getLexer().isNot(AsmToken::EndOfStatement))
7418 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007419 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00007420 Parser.Lex(); // Eat EndOfStatement token.
7421 return false;
7422}
7423
Jack Carter0cd3c192014-01-06 23:27:31 +00007424bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007425 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00007426 // Get the option token.
7427 AsmToken Tok = Parser.getTok();
7428 // At the moment only identifiers are supported.
7429 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007430 return Error(Parser.getTok().getLoc(),
7431 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00007432 }
7433
7434 StringRef Option = Tok.getIdentifier();
7435
7436 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007437 // MipsAsmParser needs to know if the current PIC mode changes.
7438 IsPicEnabled = false;
7439
Jack Carter0cd3c192014-01-06 23:27:31 +00007440 getTargetStreamer().emitDirectiveOptionPic0();
7441 Parser.Lex();
7442 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007443 return Error(Parser.getTok().getLoc(),
7444 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007445 }
7446 return false;
7447 }
7448
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007449 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007450 // MipsAsmParser needs to know if the current PIC mode changes.
7451 IsPicEnabled = true;
7452
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007453 getTargetStreamer().emitDirectiveOptionPic2();
7454 Parser.Lex();
7455 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007456 return Error(Parser.getTok().getLoc(),
7457 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007458 }
7459 return false;
7460 }
7461
Jack Carter0cd3c192014-01-06 23:27:31 +00007462 // Unknown option.
Fangrui Songf78650a2018-07-30 19:41:25 +00007463 Warning(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007464 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007465 Parser.eatToEndOfStatement();
7466 return false;
7467}
7468
Toma Tabacu9ca50962015-04-16 09:53:47 +00007469/// parseInsnDirective
7470/// ::= .insn
7471bool MipsAsmParser::parseInsnDirective() {
7472 // If this is not the end of the statement, report an error.
7473 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7474 reportParseError("unexpected token, expected end of statement");
7475 return false;
7476 }
7477
7478 // The actual label marking happens in
7479 // MipsELFStreamer::createPendingLabelRelocs().
7480 getTargetStreamer().emitDirectiveInsn();
7481
7482 getParser().Lex(); // Eat EndOfStatement token.
7483 return false;
7484}
7485
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007486/// parseRSectionDirective
7487/// ::= .rdata
7488bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
7489 // If this is not the end of the statement, report an error.
7490 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7491 reportParseError("unexpected token, expected end of statement");
7492 return false;
7493 }
7494
7495 MCSection *ELFSection = getContext().getELFSection(
7496 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7497 getParser().getStreamer().SwitchSection(ELFSection);
7498
7499 getParser().Lex(); // Eat EndOfStatement token.
7500 return false;
7501}
7502
Simon Atanasyanbe186202016-02-11 06:45:54 +00007503/// parseSSectionDirective
7504/// ::= .sbss
7505/// ::= .sdata
7506bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7507 // If this is not the end of the statement, report an error.
7508 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7509 reportParseError("unexpected token, expected end of statement");
7510 return false;
7511 }
7512
7513 MCSection *ELFSection = getContext().getELFSection(
7514 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7515 getParser().getStreamer().SwitchSection(ELFSection);
7516
7517 getParser().Lex(); // Eat EndOfStatement token.
7518 return false;
7519}
7520
Daniel Sanders7e527422014-07-10 13:38:23 +00007521/// parseDirectiveModule
7522/// ::= .module oddspreg
7523/// ::= .module nooddspreg
7524/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007525/// ::= .module softfloat
7526/// ::= .module hardfloat
Simon Dardis805f1e02017-07-11 21:28:36 +00007527/// ::= .module mt
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007528/// ::= .module crc
7529/// ::= .module nocrc
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007530/// ::= .module virt
7531/// ::= .module novirt
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007532/// ::= .module ginv
7533/// ::= .module noginv
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007534bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007535 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007536 MCAsmLexer &Lexer = getLexer();
7537 SMLoc L = Lexer.getLoc();
7538
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007539 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007540 // TODO : get a better message.
7541 reportParseError(".module directive must appear before any code");
7542 return false;
7543 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007544
Toma Tabacuc405c822015-01-23 10:40:19 +00007545 StringRef Option;
7546 if (Parser.parseIdentifier(Option)) {
7547 reportParseError("expected .module option identifier");
7548 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007549 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007550
Toma Tabacuc405c822015-01-23 10:40:19 +00007551 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007552 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007553
Toma Tabacu3c499582015-06-25 10:56:57 +00007554 // Synchronize the abiflags information with the FeatureBits information we
7555 // changed above.
7556 getTargetStreamer().updateABIInfo(*this);
7557
7558 // If printing assembly, use the recently updated abiflags information.
7559 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7560 // emitted at the end).
7561 getTargetStreamer().emitDirectiveModuleOddSPReg();
7562
Toma Tabacuc405c822015-01-23 10:40:19 +00007563 // If this is not the end of the statement, report an error.
7564 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7565 reportParseError("unexpected token, expected end of statement");
7566 return false;
7567 }
7568
7569 return false; // parseDirectiveModule has finished successfully.
7570 } else if (Option == "nooddspreg") {
7571 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007572 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007573 }
7574
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007575 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007576
Toma Tabacu3c499582015-06-25 10:56:57 +00007577 // Synchronize the abiflags information with the FeatureBits information we
7578 // changed above.
7579 getTargetStreamer().updateABIInfo(*this);
7580
7581 // If printing assembly, use the recently updated abiflags information.
7582 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7583 // emitted at the end).
7584 getTargetStreamer().emitDirectiveModuleOddSPReg();
7585
Toma Tabacuc405c822015-01-23 10:40:19 +00007586 // If this is not the end of the statement, report an error.
7587 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7588 reportParseError("unexpected token, expected end of statement");
7589 return false;
7590 }
7591
7592 return false; // parseDirectiveModule has finished successfully.
7593 } else if (Option == "fp") {
7594 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007595 } else if (Option == "softfloat") {
7596 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7597
7598 // Synchronize the ABI Flags information with the FeatureBits information we
7599 // updated above.
7600 getTargetStreamer().updateABIInfo(*this);
7601
7602 // If printing assembly, use the recently updated ABI Flags information.
7603 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7604 // emitted later).
7605 getTargetStreamer().emitDirectiveModuleSoftFloat();
7606
7607 // If this is not the end of the statement, report an error.
7608 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7609 reportParseError("unexpected token, expected end of statement");
7610 return false;
7611 }
7612
7613 return false; // parseDirectiveModule has finished successfully.
7614 } else if (Option == "hardfloat") {
7615 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7616
7617 // Synchronize the ABI Flags information with the FeatureBits information we
7618 // updated above.
7619 getTargetStreamer().updateABIInfo(*this);
7620
7621 // If printing assembly, use the recently updated ABI Flags information.
7622 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7623 // emitted later).
7624 getTargetStreamer().emitDirectiveModuleHardFloat();
7625
7626 // If this is not the end of the statement, report an error.
7627 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7628 reportParseError("unexpected token, expected end of statement");
7629 return false;
7630 }
7631
7632 return false; // parseDirectiveModule has finished successfully.
Simon Dardis805f1e02017-07-11 21:28:36 +00007633 } else if (Option == "mt") {
7634 setModuleFeatureBits(Mips::FeatureMT, "mt");
7635
7636 // Synchronize the ABI Flags information with the FeatureBits information we
7637 // updated above.
7638 getTargetStreamer().updateABIInfo(*this);
7639
Simon Dardisd9611922017-07-11 21:36:58 +00007640 // If printing assembly, use the recently updated ABI Flags information.
Simon Dardis805f1e02017-07-11 21:28:36 +00007641 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7642 // emitted later).
7643 getTargetStreamer().emitDirectiveModuleMT();
7644
7645 // If this is not the end of the statement, report an error.
7646 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7647 reportParseError("unexpected token, expected end of statement");
7648 return false;
7649 }
7650
7651 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007652 } else if (Option == "crc") {
7653 setModuleFeatureBits(Mips::FeatureCRC, "crc");
7654
7655 // Synchronize the ABI Flags information with the FeatureBits information we
7656 // updated above.
7657 getTargetStreamer().updateABIInfo(*this);
7658
7659 // If printing assembly, use the recently updated ABI Flags information.
7660 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7661 // emitted later).
7662 getTargetStreamer().emitDirectiveModuleCRC();
7663
7664 // If this is not the end of the statement, report an error.
7665 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7666 reportParseError("unexpected token, expected end of statement");
7667 return false;
7668 }
7669
7670 return false; // parseDirectiveModule has finished successfully.
7671 } else if (Option == "nocrc") {
7672 clearModuleFeatureBits(Mips::FeatureCRC, "crc");
7673
7674 // Synchronize the ABI Flags information with the FeatureBits information we
7675 // updated above.
7676 getTargetStreamer().updateABIInfo(*this);
7677
7678 // If printing assembly, use the recently updated ABI Flags information.
7679 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7680 // emitted later).
7681 getTargetStreamer().emitDirectiveModuleNoCRC();
7682
7683 // If this is not the end of the statement, report an error.
7684 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7685 reportParseError("unexpected token, expected end of statement");
7686 return false;
7687 }
7688
7689 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007690 } else if (Option == "virt") {
7691 setModuleFeatureBits(Mips::FeatureVirt, "virt");
7692
7693 // Synchronize the ABI Flags information with the FeatureBits information we
7694 // updated above.
7695 getTargetStreamer().updateABIInfo(*this);
7696
7697 // If printing assembly, use the recently updated ABI Flags information.
7698 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7699 // emitted later).
7700 getTargetStreamer().emitDirectiveModuleVirt();
7701
7702 // If this is not the end of the statement, report an error.
7703 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7704 reportParseError("unexpected token, expected end of statement");
7705 return false;
7706 }
7707
7708 return false; // parseDirectiveModule has finished successfully.
7709 } else if (Option == "novirt") {
7710 clearModuleFeatureBits(Mips::FeatureVirt, "virt");
7711
7712 // Synchronize the ABI Flags information with the FeatureBits information we
7713 // updated above.
7714 getTargetStreamer().updateABIInfo(*this);
7715
7716 // If printing assembly, use the recently updated ABI Flags information.
7717 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7718 // emitted later).
7719 getTargetStreamer().emitDirectiveModuleNoVirt();
7720
7721 // If this is not the end of the statement, report an error.
7722 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7723 reportParseError("unexpected token, expected end of statement");
7724 return false;
7725 }
7726
7727 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007728 } else if (Option == "ginv") {
7729 setModuleFeatureBits(Mips::FeatureGINV, "ginv");
7730
7731 // Synchronize the ABI Flags information with the FeatureBits information we
7732 // updated above.
7733 getTargetStreamer().updateABIInfo(*this);
7734
7735 // If printing assembly, use the recently updated ABI Flags information.
7736 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7737 // emitted later).
7738 getTargetStreamer().emitDirectiveModuleGINV();
7739
7740 // If this is not the end of the statement, report an error.
7741 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7742 reportParseError("unexpected token, expected end of statement");
7743 return false;
7744 }
7745
7746 return false; // parseDirectiveModule has finished successfully.
7747 } else if (Option == "noginv") {
7748 clearModuleFeatureBits(Mips::FeatureGINV, "ginv");
7749
7750 // Synchronize the ABI Flags information with the FeatureBits information we
7751 // updated above.
7752 getTargetStreamer().updateABIInfo(*this);
7753
7754 // If printing assembly, use the recently updated ABI Flags information.
7755 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7756 // emitted later).
7757 getTargetStreamer().emitDirectiveModuleNoGINV();
7758
7759 // If this is not the end of the statement, report an error.
7760 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7761 reportParseError("unexpected token, expected end of statement");
7762 return false;
7763 }
7764
7765 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007766 } else {
7767 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7768 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007769}
7770
7771/// parseDirectiveModuleFP
7772/// ::= =32
7773/// ::= =xx
7774/// ::= =64
7775bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007776 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007777 MCAsmLexer &Lexer = getLexer();
7778
7779 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007780 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007781 return false;
7782 }
7783 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007784
Daniel Sanders7e527422014-07-10 13:38:23 +00007785 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007786 if (!parseFpABIValue(FpABI, ".module"))
7787 return false;
7788
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007789 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007790 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007791 return false;
7792 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007793
Toma Tabacua64e5402015-06-25 12:44:38 +00007794 // Synchronize the abiflags information with the FeatureBits information we
7795 // changed above.
7796 getTargetStreamer().updateABIInfo(*this);
7797
7798 // If printing assembly, use the recently updated abiflags information.
7799 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7800 // emitted at the end).
7801 getTargetStreamer().emitDirectiveModuleFP();
7802
Daniel Sanders7e527422014-07-10 13:38:23 +00007803 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007804 return false;
7805}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007806
Daniel Sanders7e527422014-07-10 13:38:23 +00007807bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007808 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007809 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007810 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007811 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007812
7813 if (Lexer.is(AsmToken::Identifier)) {
7814 StringRef Value = Parser.getTok().getString();
7815 Parser.Lex();
7816
7817 if (Value != "xx") {
7818 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7819 return false;
7820 }
7821
7822 if (!isABI_O32()) {
7823 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7824 return false;
7825 }
7826
Daniel Sanders7e527422014-07-10 13:38:23 +00007827 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007828 if (ModuleLevelOptions) {
7829 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7830 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7831 } else {
7832 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7833 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7834 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007835 return true;
7836 }
7837
7838 if (Lexer.is(AsmToken::Integer)) {
7839 unsigned Value = Parser.getTok().getIntVal();
7840 Parser.Lex();
7841
7842 if (Value != 32 && Value != 64) {
7843 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7844 return false;
7845 }
7846
7847 if (Value == 32) {
7848 if (!isABI_O32()) {
7849 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7850 return false;
7851 }
7852
Daniel Sanders7e527422014-07-10 13:38:23 +00007853 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007854 if (ModuleLevelOptions) {
7855 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7856 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7857 } else {
7858 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7859 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7860 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007861 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007862 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007863 if (ModuleLevelOptions) {
7864 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7865 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7866 } else {
7867 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7868 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7869 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007870 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007871
Daniel Sanders7e527422014-07-10 13:38:23 +00007872 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007873 }
7874
7875 return false;
7876}
7877
Jack Carter0b744b32012-10-04 02:29:46 +00007878bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007879 // This returns false if this function recognizes the directive
7880 // regardless of whether it is successfully handles or reports an
7881 // error. Otherwise it returns true to give the generic parser a
7882 // chance at recognizing it.
7883
Rafael Espindola961d4692014-11-11 05:18:41 +00007884 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007885 StringRef IDVal = DirectiveID.getString();
7886
Nirav Dave996fc132016-05-05 14:15:46 +00007887 if (IDVal == ".cpload") {
7888 parseDirectiveCpLoad(DirectiveID.getLoc());
7889 return false;
7890 }
7891 if (IDVal == ".cprestore") {
7892 parseDirectiveCpRestore(DirectiveID.getLoc());
7893 return false;
7894 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007895 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007896 StringRef SymbolName;
7897
7898 if (Parser.parseIdentifier(SymbolName)) {
7899 reportParseError("expected identifier after .ent");
7900 return false;
7901 }
7902
7903 // There's an undocumented extension that allows an integer to
7904 // follow the name of the procedure which AFAICS is ignored by GAS.
7905 // Example: .ent foo,2
7906 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7907 if (getLexer().isNot(AsmToken::Comma)) {
7908 // Even though we accept this undocumented extension for compatibility
7909 // reasons, the additional integer argument does not actually change
7910 // the behaviour of the '.ent' directive, so we would like to discourage
7911 // its use. We do this by not referring to the extended version in
7912 // error messages which are not directly related to its use.
7913 reportParseError("unexpected token, expected end of statement");
7914 return false;
7915 }
7916 Parser.Lex(); // Eat the comma.
7917 const MCExpr *DummyNumber;
7918 int64_t DummyNumberVal;
7919 // If the user was explicitly trying to use the extended version,
7920 // we still give helpful extension-related error messages.
7921 if (Parser.parseExpression(DummyNumber)) {
7922 reportParseError("expected number after comma");
7923 return false;
7924 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007925 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007926 reportParseError("expected an absolute expression after comma");
7927 return false;
7928 }
7929 }
7930
7931 // If this is not the end of the statement, report an error.
7932 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7933 reportParseError("unexpected token, expected end of statement");
7934 return false;
7935 }
7936
Jim Grosbach6f482002015-05-18 18:43:14 +00007937 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007938
7939 getTargetStreamer().emitDirectiveEnt(*Sym);
7940 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007941 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007942 return false;
7943 }
7944
Jack Carter07c818d2013-01-25 01:31:34 +00007945 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007946 StringRef SymbolName;
7947
7948 if (Parser.parseIdentifier(SymbolName)) {
7949 reportParseError("expected identifier after .end");
7950 return false;
7951 }
7952
7953 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7954 reportParseError("unexpected token, expected end of statement");
7955 return false;
7956 }
7957
7958 if (CurrentFn == nullptr) {
7959 reportParseError(".end used without .ent");
7960 return false;
7961 }
7962
7963 if ((SymbolName != CurrentFn->getName())) {
7964 reportParseError(".end symbol does not match .ent symbol");
7965 return false;
7966 }
7967
7968 getTargetStreamer().emitDirectiveEnd(SymbolName);
7969 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007970 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007971 return false;
7972 }
7973
Jack Carter07c818d2013-01-25 01:31:34 +00007974 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007975 // .frame $stack_reg, frame_size_in_bytes, $return_reg
7976 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007977 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007978 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7979 reportParseError("expected stack register");
7980 return false;
7981 }
7982
7983 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7984 if (!StackRegOpnd.isGPRAsmReg()) {
7985 reportParseError(StackRegOpnd.getStartLoc(),
7986 "expected general purpose register");
7987 return false;
7988 }
7989 unsigned StackReg = StackRegOpnd.getGPR32Reg();
7990
7991 if (Parser.getTok().is(AsmToken::Comma))
7992 Parser.Lex();
7993 else {
7994 reportParseError("unexpected token, expected comma");
7995 return false;
7996 }
7997
7998 // Parse the frame size.
7999 const MCExpr *FrameSize;
8000 int64_t FrameSizeVal;
8001
8002 if (Parser.parseExpression(FrameSize)) {
8003 reportParseError("expected frame size value");
8004 return false;
8005 }
8006
Jim Grosbach13760bd2015-05-30 01:25:56 +00008007 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008008 reportParseError("frame size not an absolute expression");
8009 return false;
8010 }
8011
8012 if (Parser.getTok().is(AsmToken::Comma))
8013 Parser.Lex();
8014 else {
8015 reportParseError("unexpected token, expected comma");
8016 return false;
8017 }
8018
8019 // Parse the return register.
8020 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00008021 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00008022 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
8023 reportParseError("expected return register");
8024 return false;
8025 }
8026
8027 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
8028 if (!ReturnRegOpnd.isGPRAsmReg()) {
8029 reportParseError(ReturnRegOpnd.getStartLoc(),
8030 "expected general purpose register");
8031 return false;
8032 }
8033
8034 // If this is not the end of the statement, report an error.
8035 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8036 reportParseError("unexpected token, expected end of statement");
8037 return false;
8038 }
8039
8040 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
8041 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00008042 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00008043 return false;
8044 }
8045
Jack Carter07c818d2013-01-25 01:31:34 +00008046 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00008047 parseDirectiveSet();
8048 return false;
Jack Carterbe332172012-09-07 00:48:02 +00008049 }
8050
Daniel Sandersd97a6342014-08-13 10:07:34 +00008051 if (IDVal == ".mask" || IDVal == ".fmask") {
8052 // .mask bitmask, frame_offset
8053 // bitmask: One bit for each register used.
8054 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
8055 // first register is expected to be saved.
8056 // Examples:
8057 // .mask 0x80000000, -4
8058 // .fmask 0x80000000, -4
8059 //
Jack Carterbe332172012-09-07 00:48:02 +00008060
Daniel Sandersd97a6342014-08-13 10:07:34 +00008061 // Parse the bitmask
8062 const MCExpr *BitMask;
8063 int64_t BitMaskVal;
8064
8065 if (Parser.parseExpression(BitMask)) {
8066 reportParseError("expected bitmask value");
8067 return false;
8068 }
8069
Jim Grosbach13760bd2015-05-30 01:25:56 +00008070 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008071 reportParseError("bitmask not an absolute expression");
8072 return false;
8073 }
8074
8075 if (Parser.getTok().is(AsmToken::Comma))
8076 Parser.Lex();
8077 else {
8078 reportParseError("unexpected token, expected comma");
8079 return false;
8080 }
8081
8082 // Parse the frame_offset
8083 const MCExpr *FrameOffset;
8084 int64_t FrameOffsetVal;
8085
8086 if (Parser.parseExpression(FrameOffset)) {
8087 reportParseError("expected frame offset value");
8088 return false;
8089 }
8090
Jim Grosbach13760bd2015-05-30 01:25:56 +00008091 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008092 reportParseError("frame offset not an absolute expression");
8093 return false;
8094 }
8095
8096 // If this is not the end of the statement, report an error.
8097 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8098 reportParseError("unexpected token, expected end of statement");
8099 return false;
8100 }
8101
8102 if (IDVal == ".mask")
8103 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
8104 else
8105 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00008106 return false;
8107 }
8108
Matheus Almeida0051f2d2014-04-16 15:48:55 +00008109 if (IDVal == ".nan")
8110 return parseDirectiveNaN();
8111
Jack Carter07c818d2013-01-25 01:31:34 +00008112 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00008113 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00008114 return false;
8115 }
8116
Rafael Espindolab59fb732014-03-28 18:50:26 +00008117 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00008118 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00008119 return false;
8120 }
8121
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00008122 if (IDVal == ".dtprelword") {
8123 parseDirectiveDtpRelWord();
8124 return false;
8125 }
8126
8127 if (IDVal == ".dtpreldword") {
8128 parseDirectiveDtpRelDWord();
8129 return false;
8130 }
8131
8132 if (IDVal == ".tprelword") {
8133 parseDirectiveTpRelWord();
8134 return false;
8135 }
8136
8137 if (IDVal == ".tpreldword") {
8138 parseDirectiveTpRelDWord();
8139 return false;
8140 }
8141
Nirav Dave996fc132016-05-05 14:15:46 +00008142 if (IDVal == ".option") {
8143 parseDirectiveOption();
8144 return false;
8145 }
Jack Carter0cd3c192014-01-06 23:27:31 +00008146
8147 if (IDVal == ".abicalls") {
8148 getTargetStreamer().emitDirectiveAbiCalls();
8149 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Fangrui Songf78650a2018-07-30 19:41:25 +00008150 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00008151 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00008152 }
8153 return false;
8154 }
8155
Nirav Dave996fc132016-05-05 14:15:46 +00008156 if (IDVal == ".cpsetup") {
8157 parseDirectiveCPSetup();
8158 return false;
8159 }
8160 if (IDVal == ".cpreturn") {
8161 parseDirectiveCPReturn();
8162 return false;
8163 }
8164 if (IDVal == ".module") {
8165 parseDirectiveModule();
8166 return false;
8167 }
8168 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
8169 parseInternalDirectiveReallowModule();
8170 return false;
8171 }
8172 if (IDVal == ".insn") {
8173 parseInsnDirective();
8174 return false;
8175 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00008176 if (IDVal == ".rdata") {
8177 parseRSectionDirective(".rodata");
8178 return false;
8179 }
Nirav Dave996fc132016-05-05 14:15:46 +00008180 if (IDVal == ".sbss") {
8181 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
8182 return false;
8183 }
8184 if (IDVal == ".sdata") {
8185 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
8186 return false;
8187 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00008188
Rafael Espindola870c4e92012-01-11 03:56:41 +00008189 return true;
8190}
8191
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00008192bool MipsAsmParser::parseInternalDirectiveReallowModule() {
8193 // If this is not the end of the statement, report an error.
8194 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8195 reportParseError("unexpected token, expected end of statement");
8196 return false;
8197 }
8198
8199 getTargetStreamer().reallowModuleDirective();
8200
8201 getParser().Lex(); // Eat EndOfStatement token.
8202 return false;
8203}
8204
Rafael Espindola870c4e92012-01-11 03:56:41 +00008205extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00008206 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
8207 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
8208 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
8209 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00008210}
Jack Carterb4dbc172012-09-05 23:34:03 +00008211
8212#define GET_REGISTER_MATCHER
8213#define GET_MATCHER_IMPLEMENTATION
Simon Atanasyanc49da2e2018-09-13 08:38:03 +00008214#define GET_MNEMONIC_SPELL_CHECKER
Jack Carterb4dbc172012-09-05 23:34:03 +00008215#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00008216
8217bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
8218 // Find the appropriate table for this asm variant.
8219 const MatchEntry *Start, *End;
8220 switch (VariantID) {
8221 default: llvm_unreachable("invalid variant!");
8222 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
8223 }
8224 // Search the table.
8225 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
8226 return MnemonicRange.first != MnemonicRange.second;
8227}