blob: ae70fdd37c127fe8cdeb728a10a53239cb24d3f0 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eugene Zelenkodde94e42017-01-30 23:21:32 +000010#include "MCTargetDesc/MipsABIFlagsSection.h"
Eric Christophera5762812015-01-26 17:33:46 +000011#include "MCTargetDesc/MipsABIInfo.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000012#include "MCTargetDesc/MipsBaseInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000013#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000014#include "MCTargetDesc/MipsMCTargetDesc.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Zoran Jovanovic375b60d2017-05-30 09:33:43 +000016#include "llvm/ADT/APFloat.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000017#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000018#include "llvm/ADT/SmallVector.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000019#include "llvm/ADT/StringRef.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "llvm/ADT/StringSwitch.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000021#include "llvm/ADT/Triple.h"
22#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000023#include "llvm/BinaryFormat/ELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCExpr.h"
26#include "llvm/MC/MCInst.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000027#include "llvm/MC/MCInstrDesc.h"
28#include "llvm/MC/MCObjectFileInfo.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000029#include "llvm/MC/MCParser/MCAsmLexer.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000030#include "llvm/MC/MCParser/MCAsmParser.h"
31#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000032#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000033#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000034#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000035#include "llvm/MC/MCStreamer.h"
36#include "llvm/MC/MCSubtargetInfo.h"
37#include "llvm/MC/MCSymbol.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000038#include "llvm/MC/MCSymbolELF.h"
39#include "llvm/MC/MCValue.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000043#include "llvm/Support/Debug.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000044#include "llvm/Support/ErrorHandling.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000045#include "llvm/Support/MathExtras.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000046#include "llvm/Support/SMLoc.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000047#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000048#include "llvm/Support/TargetRegistry.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000049#include "llvm/Support/raw_ostream.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000050#include <algorithm>
51#include <cassert>
52#include <cstdint>
Toma Tabacu9db22db2014-09-09 10:15:38 +000053#include <memory>
Eugene Zelenkodde94e42017-01-30 23:21:32 +000054#include <string>
55#include <utility>
Rafael Espindola870c4e92012-01-11 03:56:41 +000056
57using namespace llvm;
58
Chandler Carruthe96dd892014-04-21 22:55:11 +000059#define DEBUG_TYPE "mips-asm-parser"
60
Joey Gouly0e76fa72013-09-12 10:28:05 +000061namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000062
Joey Gouly0e76fa72013-09-12 10:28:05 +000063class MCInstrInfo;
Eugene Zelenkodde94e42017-01-30 23:21:32 +000064
65} // end namespace llvm
Joey Gouly0e76fa72013-09-12 10:28:05 +000066
Rafael Espindola870c4e92012-01-11 03:56:41 +000067namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000068
Jack Carter0b744b32012-10-04 02:29:46 +000069class MipsAssemblerOptions {
70public:
Eugene Zelenkodde94e42017-01-30 23:21:32 +000071 MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000072
Toma Tabacu9db22db2014-09-09 10:15:38 +000073 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000074 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000075 Reorder = Opts->isReorder();
76 Macro = Opts->isMacro();
77 Features = Opts->getFeatures();
78 }
79
Toma Tabacub19cf202015-04-27 13:12:59 +000080 unsigned getATRegIndex() const { return ATReg; }
81 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000082 if (Reg > 31)
83 return false;
84
85 ATReg = Reg;
86 return true;
87 }
Jack Carter0b744b32012-10-04 02:29:46 +000088
Toma Tabacu9db22db2014-09-09 10:15:38 +000089 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000090 void setReorder() { Reorder = true; }
91 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000092
Toma Tabacu9db22db2014-09-09 10:15:38 +000093 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000094 void setMacro() { Macro = true; }
95 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000096
Toma Tabacu465acfd2015-06-09 13:33:26 +000097 const FeatureBitset &getFeatures() const { return Features; }
98 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000099
Daniel Sandersf0df2212014-08-04 12:20:00 +0000100 // Set of features that are either architecture features or referenced
101 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
102 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
103 // The reason we need this mask is explained in the selectArch function.
104 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000105 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +0000106
Jack Carter0b744b32012-10-04 02:29:46 +0000107private:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000108 unsigned ATReg = 1;
109 bool Reorder = true;
110 bool Macro = true;
Toma Tabacu465acfd2015-06-09 13:33:26 +0000111 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +0000112};
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000113
114} // end anonymous namespace
Jack Carter0b744b32012-10-04 02:29:46 +0000115
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000116const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
117 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
118 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
119 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
120 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
121 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
122 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
123 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
124 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
125};
126
Jack Carter0b744b32012-10-04 02:29:46 +0000127namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000128
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000130 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000131 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000132 return static_cast<MipsTargetStreamer &>(TS);
133 }
134
Eric Christophera5762812015-01-26 17:33:46 +0000135 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000136 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000137 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
138 // nullptr, which indicates that no function is currently
139 // selected. This usually happens after an '.end func'
140 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000141 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000142 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000143 bool IsCpRestoreSet;
144 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000145 unsigned CpSaveLocation;
146 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
147 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000148
Simon Atanasyan69301c92018-05-29 15:58:06 +0000149 // Map of register aliases created via the .set directive.
150 StringMap<AsmToken> RegisterSets;
151
Daniel Sandersef638fe2014-10-03 15:37:37 +0000152 // Print a warning along with its fix-it message at the given range.
153 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
154 SMRange Range, bool ShowColors = true);
155
Simon Dardis6a319922018-05-25 16:15:48 +0000156 void ConvertXWPOperands(MCInst &Inst, const OperandVector &Operands);
157
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000158#define GET_ASSEMBLER_HEADER
159#include "MipsGenAsmMatcher.inc"
160
Daniel Sandersc5537422016-07-27 13:49:44 +0000161 unsigned
162 checkEarlyTargetMatchPredicate(MCInst &Inst,
163 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000164 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
165
Chad Rosier49963552012-10-13 00:26:04 +0000166 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000167 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000168 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000169 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000170
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000171 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000172 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000173
Toma Tabacu13964452014-09-04 13:23:44 +0000174 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000175
Toma Tabacu13964452014-09-04 13:23:44 +0000176 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000177
Craig Topper55bc6cb2017-02-08 02:54:12 +0000178 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
179
David Blaikie960ea3f2014-06-08 16:18:35 +0000180 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
181 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000182
Craig Topper56c590a2014-04-29 07:58:02 +0000183 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000184
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000185 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
186 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000187 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000188 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000189 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
Simon Atanasyan69301c92018-05-29 15:58:06 +0000190 const AsmToken &Token,
191 SMLoc S);
192 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000193 SMLoc S);
194 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
195 OperandMatchResultTy parseImm(OperandVector &Operands);
196 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
197 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000198 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
199 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000200
David Blaikie960ea3f2014-06-08 16:18:35 +0000201 bool searchSymbolAlias(OperandVector &Operands);
202
Toma Tabacu13964452014-09-04 13:23:44 +0000203 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000204
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000205 enum MacroExpanderResultTy {
206 MER_NotAMacro,
207 MER_Success,
208 MER_Fail,
209 };
Jack Carter30a59822012-10-04 04:03:53 +0000210
Matheus Almeida3813d572014-06-19 14:39:14 +0000211 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000212 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
213 MCStreamer &Out,
214 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000215
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000216 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
217 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000218
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000219 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000220 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000221 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000222
Toma Tabacuf712ede2015-06-17 14:31:51 +0000223 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
224 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000225 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000226
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000227 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
228
Toma Tabacu00e98672015-05-01 12:19:27 +0000229 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000230 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000231
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000232 bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU,
233 SMLoc IDLoc, MCStreamer &Out,
234 const MCSubtargetInfo *STI);
235
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000236 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
237 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000238 SMLoc IDLoc, MCStreamer &Out,
239 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000240
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000241 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
242 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000243
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000244 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Simon Atanasyana1882672018-05-24 07:36:11 +0000245 const MCSubtargetInfo *STI, bool IsLoad);
Daniel Sandersfba875f2016-04-29 13:43:45 +0000246
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000247 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
248 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000249
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000250 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
251 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000252
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000253 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
254 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000255
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000256 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
257 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000258
Stefan Maksimovic0a239982018-07-09 13:06:44 +0000259 bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
260 const MCSubtargetInfo *STI, const bool IsMips64,
261 const bool Signed);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000262
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000263 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000264 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000265
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000266 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
267 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000268
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000269 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
270 const MCSubtargetInfo *STI);
271
272 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000273 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000274
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000275 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000276 MCStreamer &Out, const MCSubtargetInfo *STI);
277 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
278 const MCSubtargetInfo *STI);
279 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
280 const MCSubtargetInfo *STI);
281 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
282 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000283
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000284 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
285 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000286
Simon Dardis3c82a642017-02-08 16:25:05 +0000287 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
288 const MCSubtargetInfo *STI);
289
290 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
291 const MCSubtargetInfo *STI);
292
293 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
294 const MCSubtargetInfo *STI);
295
296 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
297 const MCSubtargetInfo *STI);
298
Simon Dardisaff4d142016-10-18 14:28:00 +0000299 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
300 const MCSubtargetInfo *STI, bool IsLoad);
301
Simon Dardis43115a12016-11-21 20:30:41 +0000302 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
303 const MCSubtargetInfo *STI);
304
305 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
306 const MCSubtargetInfo *STI);
307
Simon Dardisde5ed0c2017-11-14 22:26:42 +0000308 bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
309 const MCSubtargetInfo *STI);
310
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000311 bool reportParseError(Twine ErrorMsg);
312 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000313
Jack Carterb5cf5902013-04-17 00:18:04 +0000314 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000315
316 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000317 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000318 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000319 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000320 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000321 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000322 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000323 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000324 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000325 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000326 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000327 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000328 bool parseInsnDirective();
Simon Dardis1c73fcc2017-06-22 10:41:51 +0000329 bool parseRSectionDirective(StringRef Section);
Simon Atanasyanbe186202016-02-11 06:45:54 +0000330 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000331
332 bool parseSetAtDirective();
333 bool parseSetNoAtDirective();
334 bool parseSetMacroDirective();
335 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000336 bool parseSetMsaDirective();
337 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000338 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000339 bool parseSetReorderDirective();
340 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000341 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000342 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000343 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000344 bool parseSetOddSPRegDirective();
345 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000346 bool parseSetPopDirective();
347 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000348 bool parseSetSoftFloatDirective();
349 bool parseSetHardFloatDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +0000350 bool parseSetMtDirective();
351 bool parseSetNoMtDirective();
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000352 bool parseSetNoCRCDirective();
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000353 bool parseSetNoVirtDirective();
Petar Jovanovicdaf51692018-05-17 16:30:32 +0000354 bool parseSetNoGINVDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000355
Jack Carterd76b2372013-03-21 21:44:16 +0000356 bool parseSetAssignment();
357
Vladimir Medic4c299852013-11-06 11:27:05 +0000358 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000359 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000360 bool parseDirectiveDtpRelWord();
361 bool parseDirectiveDtpRelDWord();
362 bool parseDirectiveTpRelWord();
363 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000364 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000365 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000366 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
367 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000368
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000369 bool parseInternalDirectiveReallowModule();
370
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000371 bool eatComma(StringRef ErrorStr);
372
Jack Carter1ac53222013-02-20 23:11:17 +0000373 int matchCPURegisterName(StringRef Symbol);
374
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000375 int matchHWRegsRegisterName(StringRef Symbol);
376
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000377 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000378
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000379 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000380
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000381 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000382
Jack Carter5dc8ac92013-09-25 23:50:44 +0000383 int matchMSA128RegisterName(StringRef Name);
384
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000385 int matchMSA128CtrlRegisterName(StringRef Name);
386
Jack Carterd0bd6422013-04-18 00:41:53 +0000387 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000388
Toma Tabacu89a712b2015-04-15 10:48:56 +0000389 /// Returns the internal register number for the current AT. Also checks if
390 /// the current AT is unavailable (set to $0) and gives an error if it is.
391 /// This should be used in pseudo-instruction expansions which need AT.
392 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000393
Simon Dardis3aa8a902017-02-06 12:43:46 +0000394 bool canUseATReg();
395
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000396 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
397 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000398
399 // Helper function that checks if the value of a vector index is within the
400 // boundaries of accepted values for each RegisterKind
401 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
402 bool validateMSAIndex(int Val, int RegKind);
403
Daniel Sandersf0df2212014-08-04 12:20:00 +0000404 // Selects a new architecture by updating the FeatureBits with the necessary
405 // info including implied dependencies.
406 // Internally, it clears all the feature bits related to *any* architecture
407 // and selects the new one using the ToggleFeature functionality of the
408 // MCSubtargetInfo object that handles implied dependencies. The reason we
409 // clear all the arch related bits manually is because ToggleFeature only
410 // clears the features that imply the feature being cleared and not the
411 // features implied by the feature being cleared. This is easier to see
412 // with an example:
413 // --------------------------------------------------
414 // | Feature | Implies |
415 // | -------------------------------------------------|
416 // | FeatureMips1 | None |
417 // | FeatureMips2 | FeatureMips1 |
418 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
419 // | FeatureMips4 | FeatureMips3 |
420 // | ... | |
421 // --------------------------------------------------
422 //
423 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
424 // FeatureMipsGP64 | FeatureMips1)
425 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
426 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000427 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000428 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000429 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
430 STI.setFeatureBits(FeatureBits);
431 setAvailableFeatures(
432 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000433 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000434 }
435
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000436 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000437 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000438 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000439 setAvailableFeatures(
440 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000441 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000442 }
443 }
444
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000445 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000446 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000447 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000448 setAvailableFeatures(
449 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000450 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000451 }
452 }
453
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000454 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
455 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000456 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000457 }
458
459 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
460 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000461 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000462 }
463
Rafael Espindola870c4e92012-01-11 03:56:41 +0000464public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000465 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000466 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000467 Match_RequiresDifferentOperands,
468 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000469 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000470 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000471 Match_NonZeroOperandForSync,
Simon Dardis52ae4f02018-03-07 11:39:48 +0000472 Match_NonZeroOperandForMTCX,
Simon Dardis6f83ae32017-09-14 15:17:50 +0000473 Match_RequiresPosSizeRange0_32,
474 Match_RequiresPosSizeRange33_64,
Simon Dardis55e44672017-09-14 17:27:53 +0000475 Match_RequiresPosSizeUImm6,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000476#define GET_OPERAND_DIAGNOSTIC_TYPES
477#include "MipsGenAsmMatcher.inc"
478#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000479 };
480
Akira Hatanakab11ef082015-11-14 06:35:56 +0000481 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000482 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000483 : MCTargetAsmParser(Options, sti, MII),
Daniel Sanders50f17232015-09-15 16:17:27 +0000484 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
485 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000486 MCAsmParserExtension::Initialize(parser);
487
Toma Tabacu11e14a92015-04-21 11:50:52 +0000488 parser.addAliasForDirective(".asciiz", ".asciz");
Simon Atanasyanb5244592018-07-25 07:07:43 +0000489 parser.addAliasForDirective(".hword", ".2byte");
490 parser.addAliasForDirective(".word", ".4byte");
491 parser.addAliasForDirective(".dword", ".8byte");
Toma Tabacu11e14a92015-04-21 11:50:52 +0000492
Jack Carterb4dbc172012-09-05 23:34:03 +0000493 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000494 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000495
Toma Tabacu9db22db2014-09-09 10:15:38 +0000496 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000497 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000498 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000499
Toma Tabacu9db22db2014-09-09 10:15:38 +0000500 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000501 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000502 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000503
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000504 getTargetStreamer().updateABIInfo(*this);
505
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000506 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000507 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000508
509 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000510
Rafael Espindola699281c2016-05-18 11:58:50 +0000511 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000512
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000513 IsCpRestoreSet = false;
514 CpRestoreOffset = -1;
515
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000516 const Triple &TheTriple = sti.getTargetTriple();
Alexander Richardson85e200e2018-06-25 16:49:20 +0000517 IsLittleEndian = TheTriple.isLittleEndian();
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +0000518
519 if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
520 report_fatal_error("microMIPS64R6 is not supported", false);
Simon Dardisaf38a8f2018-06-19 16:05:44 +0000521
522 if (!isABI_O32() && inMicroMipsMode())
523 report_fatal_error("microMIPS64 is not supported", false);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000524 }
525
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000526 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
527 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
528
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000529 bool isGP64bit() const {
530 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
531 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000532
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000533 bool isFP64bit() const {
534 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
535 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000536
Eric Christophera5762812015-01-26 17:33:46 +0000537 const MipsABIInfo &getABI() const { return ABI; }
538 bool isABI_N32() const { return ABI.IsN32(); }
539 bool isABI_N64() const { return ABI.IsN64(); }
540 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000541 bool isABI_FPXX() const {
542 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
543 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000544
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000545 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000546 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000547 }
548
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000549 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000550 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000551 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000552
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000553 bool hasMips1() const {
554 return getSTI().getFeatureBits()[Mips::FeatureMips1];
555 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000556
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000557 bool hasMips2() const {
558 return getSTI().getFeatureBits()[Mips::FeatureMips2];
559 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000560
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000561 bool hasMips3() const {
562 return getSTI().getFeatureBits()[Mips::FeatureMips3];
563 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000564
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000565 bool hasMips4() const {
566 return getSTI().getFeatureBits()[Mips::FeatureMips4];
567 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000568
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000569 bool hasMips5() const {
570 return getSTI().getFeatureBits()[Mips::FeatureMips5];
571 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000572
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000573 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000574 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000575 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000576
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000577 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000578 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000579 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000580
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000581 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000582 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000583 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000584
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000585 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000586 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000587 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000588
Daniel Sanders17793142015-02-18 16:24:50 +0000589 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000590 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000591 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000592
Daniel Sanders17793142015-02-18 16:24:50 +0000593 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000594 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000595 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000596
Daniel Sanders17793142015-02-18 16:24:50 +0000597 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000598 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000599 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000600
Daniel Sanders17793142015-02-18 16:24:50 +0000601 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000602 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000603 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000604
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000605 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000606 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000607 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000608
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000609 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000610 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000611 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000612
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000613 bool hasDSP() const {
614 return getSTI().getFeatureBits()[Mips::FeatureDSP];
615 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000616
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000617 bool hasDSPR2() const {
618 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
619 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000620
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000621 bool hasDSPR3() const {
622 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
623 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000624
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000625 bool hasMSA() const {
626 return getSTI().getFeatureBits()[Mips::FeatureMSA];
627 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000628
Kai Nackee0245392015-01-27 19:11:28 +0000629 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000630 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000631 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000632
Daniel Sandersa6994442015-08-18 12:33:54 +0000633 bool inPicMode() {
634 return IsPicEnabled;
635 }
636
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000637 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000638 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000639 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000640
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000641 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000642 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000643 }
644
Eric Christophere8ae3e32015-05-07 23:10:21 +0000645 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000646 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000647 }
Simon Dardisae719c52017-07-11 18:03:20 +0000648 bool hasMT() const {
649 return getSTI().getFeatureBits()[Mips::FeatureMT];
650 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000651
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000652 bool hasCRC() const {
653 return getSTI().getFeatureBits()[Mips::FeatureCRC];
654 }
655
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000656 bool hasVirt() const {
657 return getSTI().getFeatureBits()[Mips::FeatureVirt];
658 }
659
Petar Jovanovicdaf51692018-05-17 16:30:32 +0000660 bool hasGINV() const {
661 return getSTI().getFeatureBits()[Mips::FeatureGINV];
662 }
663
Toma Tabacud9d344b2015-04-27 14:05:04 +0000664 /// Warn if RegIndex is the same as the current AT.
665 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000666
667 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000668
669 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000670
671 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
672 AsmToken::TokenKind OperatorToken,
673 MCContext &Ctx) override {
674 switch(OperatorToken) {
675 default:
676 llvm_unreachable("Unknown token");
677 return nullptr;
678 case AsmToken::PercentCall16:
679 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
680 case AsmToken::PercentCall_Hi:
681 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
682 case AsmToken::PercentCall_Lo:
683 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
684 case AsmToken::PercentDtprel_Hi:
685 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
686 case AsmToken::PercentDtprel_Lo:
687 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
688 case AsmToken::PercentGot:
689 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
690 case AsmToken::PercentGot_Disp:
691 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
692 case AsmToken::PercentGot_Hi:
693 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
694 case AsmToken::PercentGot_Lo:
695 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
696 case AsmToken::PercentGot_Ofst:
697 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
698 case AsmToken::PercentGot_Page:
699 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
700 case AsmToken::PercentGottprel:
701 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
702 case AsmToken::PercentGp_Rel:
703 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
704 case AsmToken::PercentHi:
705 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
706 case AsmToken::PercentHigher:
707 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
708 case AsmToken::PercentHighest:
709 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
710 case AsmToken::PercentLo:
711 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
712 case AsmToken::PercentNeg:
713 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
714 case AsmToken::PercentPcrel_Hi:
715 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
716 case AsmToken::PercentPcrel_Lo:
717 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
718 case AsmToken::PercentTlsgd:
719 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
720 case AsmToken::PercentTlsldm:
721 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
722 case AsmToken::PercentTprel_Hi:
723 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
724 case AsmToken::PercentTprel_Lo:
725 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
726 }
727 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000728};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000729
730/// MipsOperand - Instances of this class represent a parsed Mips machine
731/// instruction.
732class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000733public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000734 /// Broad categories of register classes
735 /// The exact class is finalized by the render method.
736 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000737 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000738 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000739 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000740 RegKind_FCC = 4, /// FCC
741 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
742 RegKind_MSACtrl = 16, /// MSA control registers
743 RegKind_COP2 = 32, /// COP2
744 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
745 /// context).
746 RegKind_CCR = 128, /// CCR
747 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000748 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000749 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000750 /// Potentially any (e.g. $1)
751 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
752 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000753 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000754 };
755
756private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000757 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000758 k_Immediate, /// An immediate (possibly involving symbol references)
759 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000760 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000761 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000762 k_RegList, /// A physical register list
763 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000764 } Kind;
765
David Blaikie960ea3f2014-06-08 16:18:35 +0000766public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000767 MipsOperand(KindTy K, MipsAsmParser &Parser)
768 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
769
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000770 ~MipsOperand() override {
771 switch (Kind) {
772 case k_Immediate:
773 break;
774 case k_Memory:
775 delete Mem.Base;
776 break;
777 case k_RegList:
778 delete RegList.List;
779 case k_RegisterIndex:
780 case k_Token:
781 case k_RegPair:
782 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
Daniel Sanders21bce302014-04-01 12:35:23 +00001041 /// Render the operand to an MCInst as a GPR64
1042 /// Asserts if the wrong number of operands are requested, or the operand
1043 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001044 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1045 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001046 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001047 }
1048
1049 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1050 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001051 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001052 }
1053
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001054 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1055 assert(N == 1 && "Invalid number of operands!");
1056 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1057 }
1058
1059 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1060 assert(N == 1 && "Invalid number of operands!");
1061 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1062 }
1063
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001064 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1065 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001066 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001067 }
1068
1069 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1070 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001071 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001072 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001073 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001074 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001075 AsmParser.getParser().printError(
1076 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1077 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001078 }
1079
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001080 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1081 assert(N == 1 && "Invalid number of operands!");
1082 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1083 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1084 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1085 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1086 "registers");
1087 }
1088
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001089 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1090 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001091 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001092 }
1093
1094 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1095 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001096 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001097 }
1098
1099 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1100 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001101 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001102 }
1103
1104 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1105 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001106 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001107 }
1108
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001109 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1110 assert(N == 1 && "Invalid number of operands!");
1111 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1112 }
1113
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001114 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1115 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001116 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001117 }
1118
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001119 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1120 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001121 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001122 }
1123
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001124 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1125 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001126 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001127 }
1128
1129 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1130 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001131 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001132 }
1133
1134 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1135 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001136 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001137 }
1138
1139 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1140 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001141 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001142 }
1143
1144 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1145 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001146 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001147 }
1148
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001149 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001150 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1151 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001152 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001153 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001154 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001155 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001156 Inst.addOperand(MCOperand::createImm(Imm));
1157 }
1158
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001159 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001160 void addSImmOperands(MCInst &Inst, unsigned N) const {
1161 if (isImm() && !isConstantImm()) {
1162 addExpr(Inst, getImm());
1163 return;
1164 }
1165 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1166 }
1167
1168 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001169 void addUImmOperands(MCInst &Inst, unsigned N) const {
1170 if (isImm() && !isConstantImm()) {
1171 addExpr(Inst, getImm());
1172 return;
1173 }
1174 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1175 }
1176
Daniel Sanders78e89022016-03-11 11:37:50 +00001177 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1178 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1179 assert(N == 1 && "Invalid number of operands!");
1180 int64_t Imm = getConstantImm() - Offset;
1181 Imm = SignExtend64<Bits>(Imm);
1182 Imm += Offset;
1183 Imm += AdjustOffset;
1184 Inst.addOperand(MCOperand::createImm(Imm));
1185 }
1186
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001187 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001188 assert(N == 1 && "Invalid number of operands!");
1189 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001190 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001191 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001192
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001193 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001194 assert(N == 2 && "Invalid number of operands!");
1195
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001196 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1197 ? getMemBase()->getGPR64Reg()
1198 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001199
1200 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001201 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001202 }
1203
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001204 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1205 assert(N == 2 && "Invalid number of operands!");
1206
Jim Grosbache9119e42015-05-13 18:37:00 +00001207 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001208
1209 const MCExpr *Expr = getMemOff();
1210 addExpr(Inst, Expr);
1211 }
1212
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001213 void addRegListOperands(MCInst &Inst, unsigned N) const {
1214 assert(N == 1 && "Invalid number of operands!");
1215
1216 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001217 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001218 }
1219
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001220 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1221 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001222 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001223 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001224 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1225 Inst.addOperand(MCOperand::createReg(
1226 RegIdx.RegInfo->getRegClass(
1227 AsmParser.getABI().AreGprs64bit()
1228 ? Mips::GPR64RegClassID
1229 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1230 Inst.addOperand(MCOperand::createReg(
1231 RegIdx.RegInfo->getRegClass(
1232 AsmParser.getABI().AreGprs64bit()
1233 ? Mips::GPR64RegClassID
1234 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001235 }
1236
Zoran Jovanovic41688672015-02-10 16:36:20 +00001237 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1238 assert(N == 2 && "Invalid number of operands!");
1239 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001240 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001241 }
1242
Craig Topper56c590a2014-04-29 07:58:02 +00001243 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001244 // As a special case until we sort out the definition of div/divu, accept
1245 // $0/$zero here so that MCK_ZERO works correctly.
1246 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001247 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001248
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001249 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001250 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001251
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001252 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001253 int64_t Res;
1254 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001255 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001256
Daniel Sanders52da7af2015-11-06 12:11:03 +00001257 bool isConstantImmz() const {
1258 return isConstantImm() && getConstantImm() == 0;
1259 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001260
Daniel Sandersea4f6532015-11-06 12:22:31 +00001261 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1262 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1263 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001264
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001265 template <unsigned Bits> bool isSImm() const {
1266 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1267 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001268
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001269 template <unsigned Bits> bool isUImm() const {
1270 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1271 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001272
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001273 template <unsigned Bits> bool isAnyImm() const {
1274 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1275 isUInt<Bits>(getConstantImm()))
1276 : isImm();
1277 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001278
Daniel Sanders78e89022016-03-11 11:37:50 +00001279 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1280 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001281 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001282
Hrvoje Varga46458d02016-02-25 12:53:29 +00001283 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1284 return isConstantImm() && getConstantImm() >= Bottom &&
1285 getConstantImm() <= Top;
1286 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001287
Craig Topper56c590a2014-04-29 07:58:02 +00001288 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001289 // Note: It's not possible to pretend that other operand kinds are tokens.
1290 // The matcher emitter checks tokens first.
1291 return Kind == k_Token;
1292 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001293
Craig Topper56c590a2014-04-29 07:58:02 +00001294 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001295
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001296 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001297 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001298 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001299
Simon Dardis4ccda502016-05-27 13:56:36 +00001300 // Allow relocation operators.
1301 // FIXME: This predicate and others need to look through binary expressions
1302 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001303 template <unsigned Bits, unsigned ShiftAmount = 0>
1304 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001305 if (!isMem())
1306 return false;
1307 if (!getMemBase()->isGPRAsmReg())
1308 return false;
1309 if (isa<MCTargetExpr>(getMemOff()) ||
1310 (isConstantMemOff() &&
1311 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1312 return true;
1313 MCValue Res;
1314 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1315 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001316 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001317
Simon Atanasyand4d892f2018-04-26 19:55:28 +00001318 bool isMemWithPtrSizeOffset() const {
1319 if (!isMem())
1320 return false;
1321 if (!getMemBase()->isGPRAsmReg())
1322 return false;
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00001323 const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32;
Simon Atanasyand4d892f2018-04-26 19:55:28 +00001324 if (isa<MCTargetExpr>(getMemOff()) ||
1325 (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))
1326 return true;
1327 MCValue Res;
1328 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1329 return IsReloc && isIntN(PtrBits, Res.getConstant());
1330 }
1331
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001332 bool isMemWithGRPMM16Base() const {
1333 return isMem() && getMemBase()->isMM16AsmReg();
1334 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001335
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001336 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1337 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1338 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1339 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001340
Jozef Kolek12c69822014-12-23 16:16:33 +00001341 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1342 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1343 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1344 && (getMemBase()->getGPR32Reg() == Mips::SP);
1345 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001346
Daniel Sanderse473dc92016-05-09 13:38:25 +00001347 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1348 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1349 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1350 && (getMemBase()->getGPR32Reg() == Mips::GP);
1351 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001352
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001353 template <unsigned Bits, unsigned ShiftLeftAmount>
1354 bool isScaledUImm() const {
1355 return isConstantImm() &&
1356 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001357 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001358
Daniel Sanders97297772016-03-22 14:40:00 +00001359 template <unsigned Bits, unsigned ShiftLeftAmount>
1360 bool isScaledSImm() const {
Simon Atanasyan478220f2018-05-24 07:36:00 +00001361 if (isConstantImm() &&
1362 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001363 return true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00001364 // Operand can also be a symbol or symbol plus
1365 // offset in case of relocations.
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001366 if (Kind != k_Immediate)
1367 return false;
1368 MCValue Res;
1369 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1370 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001371 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001372
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001373 bool isRegList16() const {
1374 if (!isRegList())
1375 return false;
1376
1377 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001378 if (Size < 2 || Size > 5)
1379 return false;
1380
1381 unsigned R0 = RegList.List->front();
1382 unsigned R1 = RegList.List->back();
1383 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1384 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001385 return false;
1386
1387 int PrevReg = *RegList.List->begin();
1388 for (int i = 1; i < Size - 1; i++) {
1389 int Reg = (*(RegList.List))[i];
1390 if ( Reg != PrevReg + 1)
1391 return false;
1392 PrevReg = Reg;
1393 }
1394
1395 return true;
1396 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001397
Vladimir Medic2b953d02013-10-01 09:48:56 +00001398 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001399
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001400 bool isLSAImm() const {
1401 if (!isConstantImm())
1402 return false;
1403 int64_t Val = getConstantImm();
1404 return 1 <= Val && Val <= 4;
1405 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001406
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001407 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001408
Zoran Jovanovic41688672015-02-10 16:36:20 +00001409 bool isMovePRegPair() const {
1410 if (Kind != k_RegList || RegList.List->size() != 2)
1411 return false;
1412
1413 unsigned R0 = RegList.List->front();
1414 unsigned R1 = RegList.List->back();
1415
1416 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1417 (R0 == Mips::A1 && R1 == Mips::A3) ||
1418 (R0 == Mips::A2 && R1 == Mips::A3) ||
1419 (R0 == Mips::A0 && R1 == Mips::S5) ||
1420 (R0 == Mips::A0 && R1 == Mips::S6) ||
1421 (R0 == Mips::A0 && R1 == Mips::A1) ||
1422 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001423 (R0 == Mips::A0 && R1 == Mips::A3) ||
1424 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1425 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1426 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1427 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1428 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1429 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1430 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1431 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001432 return true;
1433
1434 return false;
1435 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001436
1437 StringRef getToken() const {
1438 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001439 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001440 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001441
Craig Topper56c590a2014-04-29 07:58:02 +00001442 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001443 // As a special case until we sort out the definition of div/divu, accept
1444 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001445 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1446 RegIdx.Kind & RegKind_GPR)
1447 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001448
Daniel Sanders976d9382016-07-05 13:38:40 +00001449 llvm_unreachable("Invalid access!");
1450 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001451 }
1452
Jack Carterb4dbc172012-09-05 23:34:03 +00001453 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001454 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001455 return Imm.Val;
1456 }
1457
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001458 int64_t getConstantImm() const {
1459 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001460 int64_t Value = 0;
1461 (void)Val->evaluateAsAbsolute(Value);
1462 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001463 }
1464
1465 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001466 assert((Kind == k_Memory) && "Invalid access!");
1467 return Mem.Base;
1468 }
1469
1470 const MCExpr *getMemOff() const {
1471 assert((Kind == k_Memory) && "Invalid access!");
1472 return Mem.Off;
1473 }
1474
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001475 int64_t getConstantMemOff() const {
1476 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1477 }
1478
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001479 const SmallVectorImpl<unsigned> &getRegList() const {
1480 assert((Kind == k_RegList) && "Invalid access!");
1481 return *(RegList.List);
1482 }
1483
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001484 unsigned getRegPair() const {
1485 assert((Kind == k_RegPair) && "Invalid access!");
1486 return RegIdx.Index;
1487 }
1488
David Blaikie960ea3f2014-06-08 16:18:35 +00001489 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1490 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001491 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001492 Op->Tok.Data = Str.data();
1493 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001494 Op->StartLoc = S;
1495 Op->EndLoc = S;
1496 return Op;
1497 }
1498
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001499 /// Create a numeric register (e.g. $1). The exact register remains
1500 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001501 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001502 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1503 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001504 LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001505 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001506 }
1507
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001508 /// Create a register that is definitely a GPR.
1509 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001510 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001511 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1512 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1513 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001514 }
1515
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001516 /// Create a register that is definitely a FGR.
1517 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001518 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001519 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1520 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1521 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001522 }
1523
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001524 /// Create a register that is definitely a HWReg.
1525 /// This is typically only used for named registers such as $hwr_cpunum.
1526 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001527 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001528 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001529 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001530 }
1531
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001532 /// Create a register that is definitely an FCC.
1533 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001534 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001535 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1536 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1537 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001538 }
1539
1540 /// Create a register that is definitely an ACC.
1541 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001542 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001543 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1544 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1545 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001546 }
1547
1548 /// Create a register that is definitely an MSA128.
1549 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001550 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001551 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1552 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1553 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001554 }
1555
1556 /// Create a register that is definitely an MSACtrl.
1557 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001558 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001559 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1560 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1561 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001562 }
1563
David Blaikie960ea3f2014-06-08 16:18:35 +00001564 static std::unique_ptr<MipsOperand>
1565 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001566 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001567 Op->Imm.Val = Val;
1568 Op->StartLoc = S;
1569 Op->EndLoc = E;
1570 return Op;
1571 }
1572
David Blaikie960ea3f2014-06-08 16:18:35 +00001573 static std::unique_ptr<MipsOperand>
1574 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1575 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001576 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001577 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001578 Op->Mem.Off = Off;
1579 Op->StartLoc = S;
1580 Op->EndLoc = E;
1581 return Op;
1582 }
1583
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001584 static std::unique_ptr<MipsOperand>
1585 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1586 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001587 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001588
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001589 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001590 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001591 Op->StartLoc = StartLoc;
1592 Op->EndLoc = EndLoc;
1593 return Op;
1594 }
1595
Daniel Sandersd044e492016-05-09 13:10:57 +00001596 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1597 SMLoc S, SMLoc E,
1598 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001599 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001600 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001601 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1602 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001603 Op->StartLoc = S;
1604 Op->EndLoc = E;
1605 return Op;
1606 }
1607
Simon Dardis509da1a2017-02-13 16:06:48 +00001608 bool isGPRZeroAsmReg() const {
1609 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1610 }
1611
1612 bool isGPRNonZeroAsmReg() const {
1613 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1614 RegIdx.Index <= 31;
1615 }
1616
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001617 bool isGPRAsmReg() const {
1618 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001619 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001620
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001621 bool isMM16AsmReg() const {
1622 if (!(isRegIdx() && RegIdx.Kind))
1623 return false;
1624 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1625 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001626
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001627 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001628 bool isMM16AsmRegZero() const {
1629 if (!(isRegIdx() && RegIdx.Kind))
1630 return false;
1631 return (RegIdx.Index == 0 ||
1632 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1633 RegIdx.Index == 17);
1634 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001635
Zoran Jovanovic41688672015-02-10 16:36:20 +00001636 bool isMM16AsmRegMoveP() const {
1637 if (!(isRegIdx() && RegIdx.Kind))
1638 return false;
1639 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1640 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1641 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001642
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001643 bool isFGRAsmReg() const {
1644 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1645 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001646 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001647
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001648 bool isStrictlyFGRAsmReg() const {
1649 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1650 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1651 }
1652
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001653 bool isHWRegsAsmReg() const {
1654 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001655 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001656
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001657 bool isCCRAsmReg() const {
1658 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001659 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001660
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001661 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001662 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1663 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001664 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001665 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001666
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001667 bool isACCAsmReg() const {
1668 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001669 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001670
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001671 bool isCOP0AsmReg() const {
1672 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1673 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001674
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001675 bool isCOP2AsmReg() const {
1676 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001677 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001678
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001679 bool isCOP3AsmReg() const {
1680 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1681 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001682
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001683 bool isMSA128AsmReg() const {
1684 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001685 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001686
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001687 bool isMSACtrlAsmReg() const {
1688 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001689 }
1690
Jack Carterb4dbc172012-09-05 23:34:03 +00001691 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001692 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001693 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001694 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001695
Craig Topper56c590a2014-04-29 07:58:02 +00001696 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001697 switch (Kind) {
1698 case k_Immediate:
1699 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001700 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001701 OS << ">";
1702 break;
1703 case k_Memory:
1704 OS << "Mem<";
1705 Mem.Base->print(OS);
1706 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001707 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001708 OS << ">";
1709 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001710 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001711 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1712 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001713 break;
1714 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001715 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001716 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001717 case k_RegList:
1718 OS << "RegList< ";
1719 for (auto Reg : (*RegList.List))
1720 OS << Reg << " ";
1721 OS << ">";
1722 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001723 case k_RegPair:
1724 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1725 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001726 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001727 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001728
1729 bool isValidForTie(const MipsOperand &Other) const {
1730 if (Kind != Other.Kind)
1731 return false;
1732
1733 switch (Kind) {
1734 default:
1735 llvm_unreachable("Unexpected kind");
1736 return false;
1737 case k_RegisterIndex: {
1738 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1739 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1740 return Token == OtherToken;
1741 }
1742 }
1743 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001744}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001745
1746} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001747
Jack Carter9e65aa32013-03-22 00:05:30 +00001748namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001749
Jack Carter9e65aa32013-03-22 00:05:30 +00001750extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001751
1752} // end namespace llvm
1753
Jack Carter9e65aa32013-03-22 00:05:30 +00001754static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1755 return MipsInsts[Opcode];
1756}
1757
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001758static bool hasShortDelaySlot(unsigned Opcode) {
1759 switch (Opcode) {
1760 case Mips::JALS_MM:
1761 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001762 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001763 case Mips::BGEZALS_MM:
1764 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001765 return true;
1766 default:
1767 return false;
1768 }
1769}
1770
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001771static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1772 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1773 return &SRExpr->getSymbol();
1774 }
1775
1776 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1777 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1778 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1779
1780 if (LHSSym)
1781 return LHSSym;
1782
1783 if (RHSSym)
1784 return RHSSym;
1785
1786 return nullptr;
1787 }
1788
1789 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1790 return getSingleMCSymbol(UExpr->getSubExpr());
1791
1792 return nullptr;
1793}
1794
1795static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1796 if (isa<MCSymbolRefExpr>(Expr))
1797 return 1;
1798
1799 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1800 return countMCSymbolRefExpr(BExpr->getLHS()) +
1801 countMCSymbolRefExpr(BExpr->getRHS());
1802
1803 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1804 return countMCSymbolRefExpr(UExpr->getSubExpr());
1805
1806 return 0;
1807}
1808
Jack Carter9e65aa32013-03-22 00:05:30 +00001809bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001810 MCStreamer &Out,
1811 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001812 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001813 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001814 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001815
Jack Carter9e65aa32013-03-22 00:05:30 +00001816 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001817
1818 if (MCID.isBranch() || MCID.isCall()) {
1819 const unsigned Opcode = Inst.getOpcode();
1820 MCOperand Offset;
1821
1822 switch (Opcode) {
1823 default:
1824 break;
Kai Nackee0245392015-01-27 19:11:28 +00001825 case Mips::BBIT0:
1826 case Mips::BBIT032:
1827 case Mips::BBIT1:
1828 case Mips::BBIT132:
1829 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001830 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001831
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001832 case Mips::BEQ:
1833 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001834 case Mips::BEQ_MM:
1835 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001836 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001837 Offset = Inst.getOperand(2);
1838 if (!Offset.isImm())
1839 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001840 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001841 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001842 if (OffsetToAlignment(Offset.getImm(),
1843 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001844 return Error(IDLoc, "branch to misaligned address");
1845 break;
1846 case Mips::BGEZ:
1847 case Mips::BGTZ:
1848 case Mips::BLEZ:
1849 case Mips::BLTZ:
1850 case Mips::BGEZAL:
1851 case Mips::BLTZAL:
1852 case Mips::BC1F:
1853 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001854 case Mips::BGEZ_MM:
1855 case Mips::BGTZ_MM:
1856 case Mips::BLEZ_MM:
1857 case Mips::BLTZ_MM:
1858 case Mips::BGEZAL_MM:
1859 case Mips::BLTZAL_MM:
1860 case Mips::BC1F_MM:
1861 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001862 case Mips::BC1EQZC_MMR6:
1863 case Mips::BC1NEZC_MMR6:
1864 case Mips::BC2EQZC_MMR6:
1865 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001866 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001867 Offset = Inst.getOperand(1);
1868 if (!Offset.isImm())
1869 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001870 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001871 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001872 if (OffsetToAlignment(Offset.getImm(),
1873 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001874 return Error(IDLoc, "branch to misaligned address");
1875 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001876 case Mips::BGEC: case Mips::BGEC_MMR6:
1877 case Mips::BLTC: case Mips::BLTC_MMR6:
1878 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1879 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1880 case Mips::BEQC: case Mips::BEQC_MMR6:
1881 case Mips::BNEC: case Mips::BNEC_MMR6:
1882 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1883 Offset = Inst.getOperand(2);
1884 if (!Offset.isImm())
1885 break; // We'll deal with this situation later on when applying fixups.
1886 if (!isIntN(18, Offset.getImm()))
1887 return Error(IDLoc, "branch target out of range");
1888 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1889 return Error(IDLoc, "branch to misaligned address");
1890 break;
1891 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1892 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1893 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1894 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1895 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1896 Offset = Inst.getOperand(1);
1897 if (!Offset.isImm())
1898 break; // We'll deal with this situation later on when applying fixups.
1899 if (!isIntN(18, Offset.getImm()))
1900 return Error(IDLoc, "branch target out of range");
1901 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1902 return Error(IDLoc, "branch to misaligned address");
1903 break;
1904 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1905 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1906 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1907 Offset = Inst.getOperand(1);
1908 if (!Offset.isImm())
1909 break; // We'll deal with this situation later on when applying fixups.
1910 if (!isIntN(23, Offset.getImm()))
1911 return Error(IDLoc, "branch target out of range");
1912 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1913 return Error(IDLoc, "branch to misaligned address");
1914 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001915 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001916 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001917 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001918 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001919 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1920 Offset = Inst.getOperand(1);
1921 if (!Offset.isImm())
1922 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001923 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001924 return Error(IDLoc, "branch target out of range");
1925 if (OffsetToAlignment(Offset.getImm(), 2LL))
1926 return Error(IDLoc, "branch to misaligned address");
1927 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001928 }
1929 }
1930
Daniel Sandersa84989a2014-06-16 13:25:35 +00001931 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1932 // We still accept it but it is a normal nop.
1933 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1934 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1935 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1936 "nop instruction");
1937 }
1938
Kai Nackee0245392015-01-27 19:11:28 +00001939 if (hasCnMips()) {
1940 const unsigned Opcode = Inst.getOpcode();
1941 MCOperand Opnd;
1942 int Imm;
1943
1944 switch (Opcode) {
1945 default:
1946 break;
1947
1948 case Mips::BBIT0:
1949 case Mips::BBIT032:
1950 case Mips::BBIT1:
1951 case Mips::BBIT132:
1952 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1953 // The offset is handled above
1954 Opnd = Inst.getOperand(1);
1955 if (!Opnd.isImm())
1956 return Error(IDLoc, "expected immediate operand kind");
1957 Imm = Opnd.getImm();
1958 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1959 Opcode == Mips::BBIT1 ? 63 : 31))
1960 return Error(IDLoc, "immediate operand value out of range");
1961 if (Imm > 31) {
1962 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1963 : Mips::BBIT132);
1964 Inst.getOperand(1).setImm(Imm - 32);
1965 }
1966 break;
1967
Kai Nackee0245392015-01-27 19:11:28 +00001968 case Mips::SEQi:
1969 case Mips::SNEi:
1970 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1971 Opnd = Inst.getOperand(2);
1972 if (!Opnd.isImm())
1973 return Error(IDLoc, "expected immediate operand kind");
1974 Imm = Opnd.getImm();
1975 if (!isInt<10>(Imm))
1976 return Error(IDLoc, "immediate operand value out of range");
1977 break;
1978 }
1979 }
1980
Simon Dardis509da1a2017-02-13 16:06:48 +00001981 // Warn on division by zero. We're checking here as all instructions get
1982 // processed here, not just the macros that need expansion.
1983 //
1984 // The MIPS backend models most of the divison instructions and macros as
1985 // three operand instructions. The pre-R6 divide instructions however have
1986 // two operands and explicitly define HI/LO as part of the instruction,
1987 // not in the operands.
1988 unsigned FirstOp = 1;
1989 unsigned SecondOp = 2;
1990 switch (Inst.getOpcode()) {
1991 default:
1992 break;
1993 case Mips::SDivIMacro:
1994 case Mips::UDivIMacro:
1995 case Mips::DSDivIMacro:
1996 case Mips::DUDivIMacro:
1997 if (Inst.getOperand(2).getImm() == 0) {
1998 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1999 Inst.getOperand(1).getReg() == Mips::ZERO_64)
2000 Warning(IDLoc, "dividing zero by zero");
2001 else
2002 Warning(IDLoc, "division by zero");
2003 }
2004 break;
2005 case Mips::DSDIV:
2006 case Mips::SDIV:
2007 case Mips::UDIV:
2008 case Mips::DUDIV:
2009 case Mips::UDIV_MM:
2010 case Mips::SDIV_MM:
2011 FirstOp = 0;
2012 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00002013 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00002014 case Mips::SDivMacro:
2015 case Mips::DSDivMacro:
2016 case Mips::UDivMacro:
2017 case Mips::DUDivMacro:
2018 case Mips::DIV:
2019 case Mips::DIVU:
2020 case Mips::DDIV:
2021 case Mips::DDIVU:
2022 case Mips::DIVU_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00002023 case Mips::DIV_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00002024 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
2025 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
2026 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
2027 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
2028 Warning(IDLoc, "dividing zero by zero");
2029 else
2030 Warning(IDLoc, "division by zero");
2031 }
2032 break;
2033 }
2034
Simon Atanasyan50485142016-12-12 17:40:26 +00002035 // For PIC code convert unconditional jump to unconditional branch.
2036 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
2037 inPicMode()) {
2038 MCInst BInst;
2039 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
2040 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2041 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2042 BInst.addOperand(Inst.getOperand(0));
2043 Inst = BInst;
2044 }
2045
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002046 // This expansion is not in a function called by tryExpandInstruction()
2047 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002048 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2049 inPicMode()) {
2050 warnIfNoMacro(IDLoc);
2051
2052 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2053
2054 // We can do this expansion if there's only 1 symbol in the argument
2055 // expression.
2056 if (countMCSymbolRefExpr(JalExpr) > 1)
2057 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2058
2059 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002060 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002061 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2062
2063 // FIXME: Add support for label+offset operands (currently causes an error).
2064 // FIXME: Add support for forward-declared local symbols.
2065 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002066 if (JalSym->isInSection() || JalSym->isTemporary() ||
Simon Atanasyan478220f2018-05-24 07:36:00 +00002067 (JalSym->isELF() &&
2068 cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002069 if (isABI_O32()) {
2070 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002071 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002072 // R_(MICRO)MIPS_GOT16 label
2073 // addiu $25, $25, 0
2074 // R_(MICRO)MIPS_LO16 label
2075 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002076 const MCExpr *Got16RelocExpr =
2077 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2078 const MCExpr *Lo16RelocExpr =
2079 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002080
Daniel Sandersa736b372016-04-29 13:33:12 +00002081 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2082 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2083 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2084 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002085 } else if (isABI_N32() || isABI_N64()) {
2086 // If it's a local symbol and the N32/N64 ABIs are being used,
2087 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002088 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002089 // R_(MICRO)MIPS_GOT_DISP label
2090 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002091 const MCExpr *GotDispRelocExpr =
2092 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002093
Daniel Sandersa736b372016-04-29 13:33:12 +00002094 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2095 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2096 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002097 }
2098 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002099 // If it's an external/weak symbol, we expand to:
2100 // lw/ld $25, 0($gp)
2101 // R_(MICRO)MIPS_CALL16 label
2102 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002103 const MCExpr *Call16RelocExpr =
2104 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002105
Daniel Sandersa736b372016-04-29 13:33:12 +00002106 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2107 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002108 }
2109
2110 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002111 if (IsCpRestoreSet && inMicroMipsMode())
2112 JalrInst.setOpcode(Mips::JALRS_MM);
2113 else
2114 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002115 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2116 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2117
2118 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2119 // This relocation is supposed to be an optimization hint for the linker
2120 // and is not necessary for correctness.
2121
2122 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002123 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002124 }
2125
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002126 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2127 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002128 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002129 // reference or immediate we may have to expand instructions.
2130 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002131 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002132 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2133 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002134 MCOperand &Op = Inst.getOperand(i);
2135 if (Op.isImm()) {
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00002136 int64_t MemOffset = Op.getImm();
Jack Carter9e65aa32013-03-22 00:05:30 +00002137 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002138 // Offset can't exceed 16bit value.
Simon Atanasyana1882672018-05-24 07:36:11 +00002139 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
Nirav Dave2364748a2016-09-16 18:30:20 +00002140 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002141 }
2142 } else if (Op.isExpr()) {
2143 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002144 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002145 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002146 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002147 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002148 // Expand symbol.
Simon Atanasyana1882672018-05-24 07:36:11 +00002149 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
Nirav Dave2364748a2016-09-16 18:30:20 +00002150 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002151 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002152 } else if (!isEvaluated(Expr)) {
Simon Atanasyana1882672018-05-24 07:36:11 +00002153 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
Nirav Dave2364748a2016-09-16 18:30:20 +00002154 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002155 }
2156 }
2157 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002158 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002159 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002160
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002161 if (inMicroMipsMode()) {
Simon Dardis6a319922018-05-25 16:15:48 +00002162 if (MCID.mayLoad() && Inst.getOpcode() != Mips::LWP_MM) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002163 // Try to create 16-bit GP relative load instruction.
2164 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2165 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2166 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2167 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2168 MCOperand &Op = Inst.getOperand(i);
2169 if (Op.isImm()) {
2170 int MemOffset = Op.getImm();
2171 MCOperand &DstReg = Inst.getOperand(0);
2172 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002173 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002174 getContext().getRegisterInfo()->getRegClass(
2175 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002176 (BaseReg.getReg() == Mips::GP ||
2177 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002178
Daniel Sandersa736b372016-04-29 13:33:12 +00002179 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2180 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002181 return false;
2182 }
2183 }
2184 }
2185 } // for
2186 } // if load
2187
2188 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2189
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002190 MCOperand Opnd;
2191 int Imm;
2192
2193 switch (Inst.getOpcode()) {
2194 default:
2195 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002196 case Mips::ADDIUSP_MM:
2197 Opnd = Inst.getOperand(0);
2198 if (!Opnd.isImm())
2199 return Error(IDLoc, "expected immediate operand kind");
2200 Imm = Opnd.getImm();
2201 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2202 Imm % 4 != 0)
2203 return Error(IDLoc, "immediate operand value out of range");
2204 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002205 case Mips::SLL16_MM:
2206 case Mips::SRL16_MM:
2207 Opnd = Inst.getOperand(2);
2208 if (!Opnd.isImm())
2209 return Error(IDLoc, "expected immediate operand kind");
2210 Imm = Opnd.getImm();
2211 if (Imm < 1 || Imm > 8)
2212 return Error(IDLoc, "immediate operand value out of range");
2213 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002214 case Mips::LI16_MM:
2215 Opnd = Inst.getOperand(1);
2216 if (!Opnd.isImm())
2217 return Error(IDLoc, "expected immediate operand kind");
2218 Imm = Opnd.getImm();
2219 if (Imm < -1 || Imm > 126)
2220 return Error(IDLoc, "immediate operand value out of range");
2221 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002222 case Mips::ADDIUR2_MM:
2223 Opnd = Inst.getOperand(2);
2224 if (!Opnd.isImm())
2225 return Error(IDLoc, "expected immediate operand kind");
2226 Imm = Opnd.getImm();
2227 if (!(Imm == 1 || Imm == -1 ||
2228 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2229 return Error(IDLoc, "immediate operand value out of range");
2230 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002231 case Mips::ANDI16_MM:
2232 Opnd = Inst.getOperand(2);
2233 if (!Opnd.isImm())
2234 return Error(IDLoc, "expected immediate operand kind");
2235 Imm = Opnd.getImm();
2236 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2237 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2238 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2239 return Error(IDLoc, "immediate operand value out of range");
2240 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002241 case Mips::LBU16_MM:
2242 Opnd = Inst.getOperand(2);
2243 if (!Opnd.isImm())
2244 return Error(IDLoc, "expected immediate operand kind");
2245 Imm = Opnd.getImm();
2246 if (Imm < -1 || Imm > 14)
2247 return Error(IDLoc, "immediate operand value out of range");
2248 break;
2249 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002250 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002251 Opnd = Inst.getOperand(2);
2252 if (!Opnd.isImm())
2253 return Error(IDLoc, "expected immediate operand kind");
2254 Imm = Opnd.getImm();
2255 if (Imm < 0 || Imm > 15)
2256 return Error(IDLoc, "immediate operand value out of range");
2257 break;
2258 case Mips::LHU16_MM:
2259 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002260 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002261 Opnd = Inst.getOperand(2);
2262 if (!Opnd.isImm())
2263 return Error(IDLoc, "expected immediate operand kind");
2264 Imm = Opnd.getImm();
2265 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2266 return Error(IDLoc, "immediate operand value out of range");
2267 break;
2268 case Mips::LW16_MM:
2269 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002270 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002271 Opnd = Inst.getOperand(2);
2272 if (!Opnd.isImm())
2273 return Error(IDLoc, "expected immediate operand kind");
2274 Imm = Opnd.getImm();
2275 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2276 return Error(IDLoc, "immediate operand value out of range");
2277 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002278 case Mips::ADDIUPC_MM:
Simon Dardis6a319922018-05-25 16:15:48 +00002279 Opnd = Inst.getOperand(1);
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002280 if (!Opnd.isImm())
2281 return Error(IDLoc, "expected immediate operand kind");
Simon Dardis6a319922018-05-25 16:15:48 +00002282 Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002283 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002284 return Error(IDLoc, "immediate operand value out of range");
2285 break;
Simon Dardis6a319922018-05-25 16:15:48 +00002286 case Mips::LWP_MM:
2287 case Mips::SWP_MM:
2288 if (Inst.getOperand(0).getReg() == Mips::RA)
2289 return Error(IDLoc, "invalid operand for instruction");
2290 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002291 }
2292 }
2293
Daniel Sandersd8c07762016-04-18 12:35:36 +00002294 bool FillDelaySlot =
2295 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2296 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002297 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002298
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002299 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002300 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002301 switch (ExpandResult) {
2302 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002303 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002304 break;
2305 case MER_Success:
2306 break;
2307 case MER_Fail:
2308 return true;
2309 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002310
Daniel Sanderscda908a2016-05-16 09:10:13 +00002311 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2312 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002313 if (inMicroMipsMode()) {
Daniel Sanderscda908a2016-05-16 09:10:13 +00002314 TOut.setUsesMicroMips();
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002315 TOut.updateABIInfo(*this);
2316 }
Daniel Sanderscda908a2016-05-16 09:10:13 +00002317
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002318 // If this instruction has a delay slot and .set reorder is active,
2319 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002320 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002321 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2322 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002323 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002324
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002325 if ((Inst.getOpcode() == Mips::JalOneReg ||
2326 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2327 isPicAndNotNxxAbi()) {
2328 if (IsCpRestoreSet) {
2329 // We need a NOP between the JALR and the LW:
2330 // If .set reorder has been used, we've already emitted a NOP.
2331 // If .set noreorder has been used, we need to emit a NOP at this point.
2332 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002333 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2334 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002335
2336 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002337 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002338 } else
2339 Warning(IDLoc, "no .cprestore used in PIC mode");
2340 }
2341
Jack Carter9e65aa32013-03-22 00:05:30 +00002342 return false;
2343}
2344
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002345MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002346MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2347 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002348 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002349 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002350 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002351 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002352 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002353 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002354 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002355 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002356 case Mips::LoadAddrImm64:
2357 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2358 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2359 "expected immediate operand kind");
2360
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002361 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2362 Inst.getOperand(1),
2363 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002364 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002365 ? MER_Fail
2366 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002367 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002368 case Mips::LoadAddrReg64:
2369 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2370 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2371 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2372 "expected immediate operand kind");
2373
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002374 return expandLoadAddress(Inst.getOperand(0).getReg(),
2375 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2376 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002377 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002378 ? MER_Fail
2379 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002380 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002381 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002382 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2383 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002384 case Mips::SWM_MM:
2385 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002386 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2387 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002388 case Mips::JalOneReg:
2389 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002390 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002391 case Mips::BneImm:
2392 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002393 case Mips::BEQLImmMacro:
2394 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002395 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002396 case Mips::BLT:
2397 case Mips::BLE:
2398 case Mips::BGE:
2399 case Mips::BGT:
2400 case Mips::BLTU:
2401 case Mips::BLEU:
2402 case Mips::BGEU:
2403 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002404 case Mips::BLTL:
2405 case Mips::BLEL:
2406 case Mips::BGEL:
2407 case Mips::BGTL:
2408 case Mips::BLTUL:
2409 case Mips::BLEUL:
2410 case Mips::BGEUL:
2411 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002412 case Mips::BLTImmMacro:
2413 case Mips::BLEImmMacro:
2414 case Mips::BGEImmMacro:
2415 case Mips::BGTImmMacro:
2416 case Mips::BLTUImmMacro:
2417 case Mips::BLEUImmMacro:
2418 case Mips::BGEUImmMacro:
2419 case Mips::BGTUImmMacro:
2420 case Mips::BLTLImmMacro:
2421 case Mips::BLELImmMacro:
2422 case Mips::BGELImmMacro:
2423 case Mips::BGTLImmMacro:
2424 case Mips::BLTULImmMacro:
2425 case Mips::BLEULImmMacro:
2426 case Mips::BGEULImmMacro:
2427 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002428 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002429 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002430 case Mips::SDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002431 case Mips::SRemMacro:
2432 case Mips::SRemIMacro:
2433 return expandDivRem(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2434 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002435 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002436 case Mips::DSDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002437 case Mips::DSRemMacro:
2438 case Mips::DSRemIMacro:
2439 return expandDivRem(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2440 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002441 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002442 case Mips::UDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002443 case Mips::URemMacro:
2444 case Mips::URemIMacro:
2445 return expandDivRem(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2446 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002447 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002448 case Mips::DUDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002449 case Mips::DURemMacro:
2450 case Mips::DURemIMacro:
2451 return expandDivRem(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2452 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002453 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002454 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2455 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002456 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002457 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002458 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002459 case Mips::PseudoTRUNC_W_D:
2460 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2461 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002462
2463 case Mips::LoadImmSingleGPR:
2464 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2465 ? MER_Fail
2466 : MER_Success;
2467 case Mips::LoadImmSingleFGR:
2468 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2469 ? MER_Fail
2470 : MER_Success;
2471 case Mips::LoadImmDoubleGPR:
2472 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2473 ? MER_Fail
2474 : MER_Success;
2475 case Mips::LoadImmDoubleFGR:
2476 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2477 ? MER_Fail
2478 : MER_Success;
2479 case Mips::LoadImmDoubleFGR_32:
2480 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2481 ? MER_Fail
2482 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002483 case Mips::Ulh:
2484 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2485 case Mips::Ulhu:
2486 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002487 case Mips::Ush:
2488 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002489 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002490 case Mips::Usw:
2491 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002492 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002493 case Mips::NORImm64:
2494 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2495 case Mips::SLTImm64:
2496 if (isInt<16>(Inst.getOperand(2).getImm())) {
2497 Inst.setOpcode(Mips::SLTi64);
2498 return MER_NotAMacro;
2499 }
2500 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2501 case Mips::SLTUImm64:
2502 if (isInt<16>(Inst.getOperand(2).getImm())) {
2503 Inst.setOpcode(Mips::SLTiu64);
2504 return MER_NotAMacro;
2505 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002506 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002507 case Mips::ADDi: case Mips::ADDi_MM:
2508 case Mips::ADDiu: case Mips::ADDiu_MM:
2509 case Mips::SLTi: case Mips::SLTi_MM:
2510 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002511 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2512 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2513 int64_t ImmValue = Inst.getOperand(2).getImm();
2514 if (isInt<16>(ImmValue))
2515 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002516 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2517 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002518 }
2519 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002520 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2521 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2522 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002523 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2524 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2525 int64_t ImmValue = Inst.getOperand(2).getImm();
2526 if (isUInt<16>(ImmValue))
2527 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002528 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2529 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002530 }
2531 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002532 case Mips::ROL:
2533 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002534 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002535 case Mips::ROLImm:
2536 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002537 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002538 case Mips::DROL:
2539 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002540 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002541 case Mips::DROLImm:
2542 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002543 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002544 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002545 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002546 case Mips::MULImmMacro:
2547 case Mips::DMULImmMacro:
2548 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2549 case Mips::MULOMacro:
2550 case Mips::DMULOMacro:
2551 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2552 case Mips::MULOUMacro:
2553 case Mips::DMULOUMacro:
2554 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2555 case Mips::DMULMacro:
2556 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002557 case Mips::LDMacro:
2558 case Mips::SDMacro:
2559 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2560 Inst.getOpcode() == Mips::LDMacro)
2561 ? MER_Fail
2562 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002563 case Mips::SEQMacro:
2564 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2565 case Mips::SEQIMacro:
2566 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisde5ed0c2017-11-14 22:26:42 +00002567 case Mips::MFTC0: case Mips::MTTC0:
2568 case Mips::MFTGPR: case Mips::MTTGPR:
2569 case Mips::MFTLO: case Mips::MTTLO:
2570 case Mips::MFTHI: case Mips::MTTHI:
2571 case Mips::MFTACX: case Mips::MTTACX:
2572 case Mips::MFTDSP: case Mips::MTTDSP:
2573 case Mips::MFTC1: case Mips::MTTC1:
2574 case Mips::MFTHC1: case Mips::MTTHC1:
2575 case Mips::CFTC1: case Mips::CTTC1:
2576 return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002577 }
Jack Carter30a59822012-10-04 04:03:53 +00002578}
Jack Carter92995f12012-10-06 00:53:28 +00002579
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002580bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002581 MCStreamer &Out,
2582 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002583 MipsTargetStreamer &TOut = getTargetStreamer();
2584
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002585 // Create a JALR instruction which is going to replace the pseudo-JAL.
2586 MCInst JalrInst;
2587 JalrInst.setLoc(IDLoc);
2588 const MCOperand FirstRegOp = Inst.getOperand(0);
2589 const unsigned Opcode = Inst.getOpcode();
2590
2591 if (Opcode == Mips::JalOneReg) {
2592 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002593 if (IsCpRestoreSet && inMicroMipsMode()) {
2594 JalrInst.setOpcode(Mips::JALRS16_MM);
2595 JalrInst.addOperand(FirstRegOp);
2596 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002597 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002598 JalrInst.addOperand(FirstRegOp);
2599 } else {
2600 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002601 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002602 JalrInst.addOperand(FirstRegOp);
2603 }
2604 } else if (Opcode == Mips::JalTwoReg) {
2605 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002606 if (IsCpRestoreSet && inMicroMipsMode())
2607 JalrInst.setOpcode(Mips::JALRS_MM);
2608 else
2609 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002610 JalrInst.addOperand(FirstRegOp);
2611 const MCOperand SecondRegOp = Inst.getOperand(1);
2612 JalrInst.addOperand(SecondRegOp);
2613 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002614 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002615
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002616 // If .set reorder is active and branch instruction has a delay slot,
2617 // emit a NOP after it.
2618 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002619 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2620 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2621 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002622
2623 return false;
2624}
2625
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002626/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002627template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002628 unsigned BitNum = findFirstSet(x);
2629
2630 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2631}
2632
2633/// Load (or add) an immediate into a register.
2634///
2635/// @param ImmValue The immediate to load.
2636/// @param DstReg The register that will hold the immediate.
2637/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2638/// for a simple initialization.
2639/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2640/// @param IsAddress True if the immediate represents an address. False if it
2641/// is an integer.
2642/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002643bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002644 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002645 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2646 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002647 MipsTargetStreamer &TOut = getTargetStreamer();
2648
Toma Tabacu00e98672015-05-01 12:19:27 +00002649 if (!Is32BitImm && !isGP64bit()) {
2650 Error(IDLoc, "instruction requires a 64-bit architecture");
2651 return true;
2652 }
2653
Daniel Sanders03f9c012015-07-14 12:24:22 +00002654 if (Is32BitImm) {
2655 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2656 // Sign extend up to 64-bit so that the predicates match the hardware
2657 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2658 // true.
2659 ImmValue = SignExtend64<32>(ImmValue);
2660 } else {
2661 Error(IDLoc, "instruction requires a 32-bit immediate");
2662 return true;
2663 }
2664 }
2665
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002666 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2667 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2668
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002669 bool UseSrcReg = false;
2670 if (SrcReg != Mips::NoRegister)
2671 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002672
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002673 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002674 if (UseSrcReg &&
2675 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002676 // At this point we need AT to perform the expansions and we exit if it is
2677 // not available.
2678 unsigned ATReg = getATReg(IDLoc);
2679 if (!ATReg)
2680 return true;
2681 TmpReg = ATReg;
2682 }
2683
Daniel Sanders03f9c012015-07-14 12:24:22 +00002684 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002685 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002686 SrcReg = ZeroReg;
2687
2688 // This doesn't quite follow the usual ABI expectations for N32 but matches
2689 // traditional assembler behaviour. N32 would normally use addiu for both
2690 // integers and addresses.
2691 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002692 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002693 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002694 }
2695
Daniel Sandersa736b372016-04-29 13:33:12 +00002696 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002697 return false;
2698 }
2699
2700 if (isUInt<16>(ImmValue)) {
2701 unsigned TmpReg = DstReg;
2702 if (SrcReg == DstReg) {
2703 TmpReg = getATReg(IDLoc);
2704 if (!TmpReg)
2705 return true;
2706 }
2707
Daniel Sandersa736b372016-04-29 13:33:12 +00002708 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002709 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002710 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002711 return false;
2712 }
2713
2714 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002715 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002716
Toma Tabacu79588102015-04-29 10:19:56 +00002717 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2718 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002719 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002720 // Traditional behaviour seems to special case this particular value. It's
2721 // not clear why other masks are handled differently.
2722 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002723 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2724 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002725 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002726 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002727 return false;
2728 }
2729
2730 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002731 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002732 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2733 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002734 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002735 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002736 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002737 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002738 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002739 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002740
Daniel Sandersa736b372016-04-29 13:33:12 +00002741 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002742 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002743 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002744 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002745 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002746 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002747 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002748
2749 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2750 if (Is32BitImm) {
2751 Error(IDLoc, "instruction requires a 32-bit immediate");
2752 return true;
2753 }
2754
2755 // Traditionally, these immediates are shifted as little as possible and as
2756 // such we align the most significant bit to bit 15 of our temporary.
2757 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2758 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2759 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2760 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002761 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2762 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002763
2764 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002765 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002766
2767 return false;
2768 }
2769
2770 warnIfNoMacro(IDLoc);
2771
2772 // The remaining case is packed with a sequence of dsll and ori with zeros
2773 // being omitted and any neighbouring dsll's being coalesced.
2774 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2775
2776 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2777 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002778 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002779 return false;
2780
2781 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2782 // skip it and defer the shift to the next chunk.
2783 unsigned ShiftCarriedForwards = 16;
2784 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2785 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2786
2787 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002788 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2789 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002790 ShiftCarriedForwards = 0;
2791 }
2792
2793 ShiftCarriedForwards += 16;
2794 }
2795 ShiftCarriedForwards -= 16;
2796
2797 // Finish any remaining shifts left by trailing zeros.
2798 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002799 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002800
2801 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002802 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002803
Matheus Almeida3813d572014-06-19 14:39:14 +00002804 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002805}
Jack Carter92995f12012-10-06 00:53:28 +00002806
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002807bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002808 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002809 const MCOperand &ImmOp = Inst.getOperand(1);
2810 assert(ImmOp.isImm() && "expected immediate operand kind");
2811 const MCOperand &DstRegOp = Inst.getOperand(0);
2812 assert(DstRegOp.isReg() && "expected register operand kind");
2813
2814 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002815 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002816 return true;
2817
2818 return false;
2819}
2820
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002821bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2822 const MCOperand &Offset,
2823 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002824 MCStreamer &Out,
2825 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002826 // la can't produce a usable address when addresses are 64-bit.
2827 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2828 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2829 // We currently can't do this because we depend on the equality
2830 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2831 Error(IDLoc, "la used to load 64-bit address");
2832 // Continue as if we had 'dla' instead.
2833 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002834 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002835 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002836
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002837 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002838 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002839 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002840 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002841 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002842
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002843 if (!Offset.isImm())
2844 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002845 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002846
Scott Egerton24557012016-01-21 15:11:01 +00002847 if (!ABI.ArePtrs64bit()) {
2848 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2849 Is32BitAddress = true;
2850 }
2851
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002852 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002853 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002854}
2855
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002856bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2857 unsigned DstReg, unsigned SrcReg,
2858 bool Is32BitSym, SMLoc IDLoc,
2859 MCStreamer &Out,
2860 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002861 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002862 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002863 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002864 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002865
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002866 if (inPicMode() && ABI.IsO32()) {
2867 MCValue Res;
2868 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2869 Error(IDLoc, "expected relocatable expression");
2870 return true;
2871 }
2872 if (Res.getSymB() != nullptr) {
2873 Error(IDLoc, "expected relocatable expression with only one symbol");
2874 return true;
2875 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002876
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002877 // The case where the result register is $25 is somewhat special. If the
2878 // symbol in the final relocation is external and not modified with a
2879 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2880 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002881 Res.getConstant() == 0 &&
2882 !(Res.getSymA()->getSymbol().isInSection() ||
2883 Res.getSymA()->getSymbol().isTemporary() ||
2884 (Res.getSymA()->getSymbol().isELF() &&
2885 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2886 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002887 const MCExpr *CallExpr =
2888 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2889 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2890 MCOperand::createExpr(CallExpr), IDLoc, STI);
2891 return false;
2892 }
2893
2894 // The remaining cases are:
2895 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2896 // >addiu $tmp, $tmp, %lo(offset)
2897 // >addiu $rd, $tmp, $rs
2898 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2899 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2900 // >addiu $rd, $tmp, $rs
2901 // The addiu's marked with a '>' may be omitted if they are redundant. If
2902 // this happens then the last instruction must use $rd as the result
2903 // register.
2904 const MipsMCExpr *GotExpr =
2905 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2906 const MCExpr *LoExpr = nullptr;
2907 if (Res.getSymA()->getSymbol().isInSection() ||
2908 Res.getSymA()->getSymbol().isTemporary())
2909 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2910 else if (Res.getConstant() != 0) {
2911 // External symbols fully resolve the symbol with just the %got(symbol)
2912 // but we must still account for any offset to the symbol for expressions
2913 // like symbol+8.
2914 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2915 }
2916
2917 unsigned TmpReg = DstReg;
2918 if (UseSrcReg &&
2919 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2920 SrcReg)) {
2921 // If $rs is the same as $rd, we need to use AT.
2922 // If it is not available we exit.
2923 unsigned ATReg = getATReg(IDLoc);
2924 if (!ATReg)
2925 return true;
2926 TmpReg = ATReg;
2927 }
2928
2929 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2930 MCOperand::createExpr(GotExpr), IDLoc, STI);
2931
2932 if (LoExpr)
2933 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2934 IDLoc, STI);
2935
2936 if (UseSrcReg)
2937 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2938
2939 return false;
2940 }
2941
Simon Dardisda96c432017-06-30 15:44:27 +00002942 if (inPicMode() && ABI.ArePtrs64bit()) {
2943 MCValue Res;
2944 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2945 Error(IDLoc, "expected relocatable expression");
2946 return true;
2947 }
2948 if (Res.getSymB() != nullptr) {
2949 Error(IDLoc, "expected relocatable expression with only one symbol");
2950 return true;
2951 }
2952
2953 // The case where the result register is $25 is somewhat special. If the
2954 // symbol in the final relocation is external and not modified with a
2955 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2956 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2957 Res.getConstant() == 0 &&
2958 !(Res.getSymA()->getSymbol().isInSection() ||
2959 Res.getSymA()->getSymbol().isTemporary() ||
2960 (Res.getSymA()->getSymbol().isELF() &&
2961 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2962 ELF::STB_LOCAL))) {
2963 const MCExpr *CallExpr =
2964 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2965 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2966 MCOperand::createExpr(CallExpr), IDLoc, STI);
2967 return false;
2968 }
2969
2970 // The remaining cases are:
2971 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2972 // >daddiu $tmp, $tmp, offset
2973 // >daddu $rd, $tmp, $rs
2974 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2975 // this happens then the last instruction must use $rd as the result
2976 // register.
2977 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2978 Res.getSymA(),
2979 getContext());
2980 const MCExpr *LoExpr = nullptr;
2981 if (Res.getConstant() != 0) {
2982 // Symbols fully resolve with just the %got_disp(symbol) but we
2983 // must still account for any offset to the symbol for
2984 // expressions like symbol+8.
2985 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2986
2987 // FIXME: Offsets greater than 16 bits are not yet implemented.
2988 // FIXME: The correct range is a 32-bit sign-extended number.
2989 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2990 Error(IDLoc, "macro instruction uses large offset, which is not "
2991 "currently supported");
2992 return true;
2993 }
2994 }
2995
2996 unsigned TmpReg = DstReg;
2997 if (UseSrcReg &&
2998 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2999 SrcReg)) {
3000 // If $rs is the same as $rd, we need to use AT.
3001 // If it is not available we exit.
3002 unsigned ATReg = getATReg(IDLoc);
3003 if (!ATReg)
3004 return true;
3005 TmpReg = ATReg;
3006 }
3007
3008 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
3009 MCOperand::createExpr(GotExpr), IDLoc, STI);
3010
3011 if (LoExpr)
3012 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3013 IDLoc, STI);
3014
3015 if (UseSrcReg)
3016 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
3017
3018 return false;
3019 }
3020
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003021 const MipsMCExpr *HiExpr =
3022 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
3023 const MipsMCExpr *LoExpr =
3024 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00003025
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003026 // This is the 64-bit symbol address expansion.
3027 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00003028 // We need AT for the 64-bit expansion in the cases where the optional
3029 // source register is the destination register and for the superscalar
3030 // scheduled form.
3031 //
3032 // If it is not available we exit if the destination is the same as the
3033 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003034
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003035 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003036 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003037 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003038 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003039
Simon Dardis3aa8a902017-02-06 12:43:46 +00003040 bool RdRegIsRsReg =
3041 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
3042
3043 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
3044 unsigned ATReg = getATReg(IDLoc);
3045
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003046 // If $rs is the same as $rd:
3047 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
3048 // daddiu $at, $at, %higher(sym)
3049 // dsll $at, $at, 16
3050 // daddiu $at, $at, %hi(sym)
3051 // dsll $at, $at, 16
3052 // daddiu $at, $at, %lo(sym)
3053 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00003054 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3055 STI);
3056 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3057 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3058 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3059 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3060 IDLoc, STI);
3061 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3062 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3063 IDLoc, STI);
3064 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003065
3066 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00003067 } else if (canUseATReg() && !RdRegIsRsReg) {
3068 unsigned ATReg = getATReg(IDLoc);
3069
3070 // If the $rs is different from $rd or if $rs isn't specified and we
3071 // have $at available:
3072 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3073 // lui $at, %hi(sym)
3074 // daddiu $rd, $rd, %higher(sym)
3075 // daddiu $at, $at, %lo(sym)
3076 // dsll32 $rd, $rd, 0
3077 // daddu $rd, $rd, $at
3078 // (daddu $rd, $rd, $rs)
3079 //
3080 // Which is preferred for superscalar issue.
3081 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3082 STI);
3083 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3084 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3085 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3086 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3087 IDLoc, STI);
3088 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3089 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3090 if (UseSrcReg)
3091 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3092
3093 return false;
3094 } else if (!canUseATReg() && !RdRegIsRsReg) {
3095 // Otherwise, synthesize the address in the destination register
3096 // serially:
3097 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3098 // daddiu $rd, $rd, %higher(sym)
3099 // dsll $rd, $rd, 16
3100 // daddiu $rd, $rd, %hi(sym)
3101 // dsll $rd, $rd, 16
3102 // daddiu $rd, $rd, %lo(sym)
3103 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3104 STI);
3105 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3106 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3107 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3108 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3109 MCOperand::createExpr(HiExpr), IDLoc, STI);
3110 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3111 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3112 MCOperand::createExpr(LoExpr), IDLoc, STI);
3113 if (UseSrcReg)
3114 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3115
3116 return false;
3117 } else {
3118 // We have a case where SrcReg == DstReg and we don't have $at
3119 // available. We can't expand this case, so error out appropriately.
3120 assert(SrcReg == DstReg && !canUseATReg() &&
3121 "Could have expanded dla but didn't?");
3122 reportParseError(IDLoc,
3123 "pseudo-instruction requires $at, which is not available");
3124 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003125 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003126 }
3127
3128 // And now, the 32-bit symbol address expansion:
3129 // If $rs is the same as $rd:
3130 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3131 // ori $at, $at, %lo(sym)
3132 // addu $rd, $at, $rd
3133 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3134 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3135 // ori $rd, $rd, %lo(sym)
3136 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003137 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003138 if (UseSrcReg &&
3139 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003140 // If $rs is the same as $rd, we need to use AT.
3141 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003142 unsigned ATReg = getATReg(IDLoc);
3143 if (!ATReg)
3144 return true;
3145 TmpReg = ATReg;
3146 }
3147
Daniel Sandersa736b372016-04-29 13:33:12 +00003148 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3149 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3150 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003151
Toma Tabacufb9d1252015-06-22 12:08:39 +00003152 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003153 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003154 else
Scott Egerton24557012016-01-21 15:11:01 +00003155 assert(
3156 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003157
Toma Tabacu674825c2015-06-16 12:16:24 +00003158 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003159}
3160
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003161// Each double-precision register DO-D15 overlaps with two of the single
3162// precision registers F0-F31. As an example, all of the following hold true:
3163// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3164static unsigned nextReg(unsigned Reg) {
3165 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3166 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3167 switch (Reg) {
3168 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3169 case Mips::ZERO: return Mips::AT;
3170 case Mips::AT: return Mips::V0;
3171 case Mips::V0: return Mips::V1;
3172 case Mips::V1: return Mips::A0;
3173 case Mips::A0: return Mips::A1;
3174 case Mips::A1: return Mips::A2;
3175 case Mips::A2: return Mips::A3;
3176 case Mips::A3: return Mips::T0;
3177 case Mips::T0: return Mips::T1;
3178 case Mips::T1: return Mips::T2;
3179 case Mips::T2: return Mips::T3;
3180 case Mips::T3: return Mips::T4;
3181 case Mips::T4: return Mips::T5;
3182 case Mips::T5: return Mips::T6;
3183 case Mips::T6: return Mips::T7;
3184 case Mips::T7: return Mips::S0;
3185 case Mips::S0: return Mips::S1;
3186 case Mips::S1: return Mips::S2;
3187 case Mips::S2: return Mips::S3;
3188 case Mips::S3: return Mips::S4;
3189 case Mips::S4: return Mips::S5;
3190 case Mips::S5: return Mips::S6;
3191 case Mips::S6: return Mips::S7;
3192 case Mips::S7: return Mips::T8;
3193 case Mips::T8: return Mips::T9;
3194 case Mips::T9: return Mips::K0;
3195 case Mips::K0: return Mips::K1;
3196 case Mips::K1: return Mips::GP;
3197 case Mips::GP: return Mips::SP;
3198 case Mips::SP: return Mips::FP;
3199 case Mips::FP: return Mips::RA;
3200 case Mips::RA: return Mips::ZERO;
3201 case Mips::D0: return Mips::F1;
3202 case Mips::D1: return Mips::F3;
3203 case Mips::D2: return Mips::F5;
3204 case Mips::D3: return Mips::F7;
3205 case Mips::D4: return Mips::F9;
3206 case Mips::D5: return Mips::F11;
3207 case Mips::D6: return Mips::F13;
3208 case Mips::D7: return Mips::F15;
3209 case Mips::D8: return Mips::F17;
3210 case Mips::D9: return Mips::F19;
3211 case Mips::D10: return Mips::F21;
3212 case Mips::D11: return Mips::F23;
3213 case Mips::D12: return Mips::F25;
3214 case Mips::D13: return Mips::F27;
3215 case Mips::D14: return Mips::F29;
3216 case Mips::D15: return Mips::F31;
3217 }
3218}
3219
3220// FIXME: This method is too general. In principle we should compute the number
3221// of instructions required to synthesize the immediate inline compared to
3222// synthesizing the address inline and relying on non .text sections.
3223// For static O32 and N32 this may yield a small benefit, for static N64 this is
3224// likely to yield a much larger benefit as we have to synthesize a 64bit
3225// address to load a 64 bit value.
3226bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3227 MCSymbol *Sym) {
3228 unsigned ATReg = getATReg(IDLoc);
3229 if (!ATReg)
3230 return true;
3231
3232 if(IsPicEnabled) {
3233 const MCExpr *GotSym =
3234 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3235 const MipsMCExpr *GotExpr =
3236 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3237
3238 if(isABI_O32() || isABI_N32()) {
3239 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3240 IDLoc, STI);
3241 } else { //isABI_N64()
3242 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3243 IDLoc, STI);
3244 }
3245 } else { //!IsPicEnabled
3246 const MCExpr *HiSym =
3247 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3248 const MipsMCExpr *HiExpr =
3249 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3250
3251 // FIXME: This is technically correct but gives a different result to gas,
3252 // but gas is incomplete there (it has a fixme noting it doesn't work with
3253 // 64-bit addresses).
3254 // FIXME: With -msym32 option, the address expansion for N64 should probably
3255 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3256 // symbol's value is considered sign extended.
3257 if(isABI_O32() || isABI_N32()) {
3258 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3259 } else { //isABI_N64()
3260 const MCExpr *HighestSym =
3261 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3262 const MipsMCExpr *HighestExpr =
3263 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3264 const MCExpr *HigherSym =
3265 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3266 const MipsMCExpr *HigherExpr =
3267 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3268
3269 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3270 STI);
3271 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3272 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3273 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3274 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3275 IDLoc, STI);
3276 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3277 }
3278 }
3279 return false;
3280}
3281
3282bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3283 bool Is64FPU, SMLoc IDLoc,
3284 MCStreamer &Out,
3285 const MCSubtargetInfo *STI) {
3286 MipsTargetStreamer &TOut = getTargetStreamer();
3287 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3288 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3289 "Invalid instruction operand.");
3290
3291 unsigned FirstReg = Inst.getOperand(0).getReg();
3292 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3293
3294 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3295 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3296 // exponent field), convert it to double (e.g. 1 to 1.0)
3297 if ((HiImmOp64 & 0x7ff00000) == 0) {
3298 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3299 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3300 }
3301
3302 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3303 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3304
3305 if (IsSingle) {
3306 // Conversion of a double in an uint64_t to a float in a uint32_t,
3307 // retaining the bit pattern of a float.
3308 uint32_t ImmOp32;
3309 double doubleImm = BitsToDouble(ImmOp64);
3310 float tmp_float = static_cast<float>(doubleImm);
3311 ImmOp32 = FloatToBits(tmp_float);
3312
3313 if (IsGPR) {
3314 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3315 Out, STI))
3316 return true;
3317 return false;
3318 } else {
3319 unsigned ATReg = getATReg(IDLoc);
3320 if (!ATReg)
3321 return true;
3322 if (LoImmOp64 == 0) {
3323 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3324 Out, STI))
3325 return true;
3326 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3327 return false;
3328 }
3329
3330 MCSection *CS = getStreamer().getCurrentSectionOnly();
3331 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3332 // where appropriate.
3333 MCSection *ReadOnlySection = getContext().getELFSection(
3334 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3335
3336 MCSymbol *Sym = getContext().createTempSymbol();
3337 const MCExpr *LoSym =
3338 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3339 const MipsMCExpr *LoExpr =
3340 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3341
3342 getStreamer().SwitchSection(ReadOnlySection);
3343 getStreamer().EmitLabel(Sym, IDLoc);
3344 getStreamer().EmitIntValue(ImmOp32, 4);
3345 getStreamer().SwitchSection(CS);
3346
3347 if(emitPartialAddress(TOut, IDLoc, Sym))
3348 return true;
3349 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3350 MCOperand::createExpr(LoExpr), IDLoc, STI);
3351 }
3352 return false;
3353 }
3354
3355 // if(!IsSingle)
3356 unsigned ATReg = getATReg(IDLoc);
3357 if (!ATReg)
3358 return true;
3359
3360 if (IsGPR) {
3361 if (LoImmOp64 == 0) {
3362 if(isABI_N32() || isABI_N64()) {
3363 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3364 IDLoc, Out, STI))
3365 return true;
3366 return false;
3367 } else {
3368 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3369 IDLoc, Out, STI))
3370 return true;
3371
3372 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3373 IDLoc, Out, STI))
3374 return true;
3375 return false;
3376 }
3377 }
3378
3379 MCSection *CS = getStreamer().getCurrentSectionOnly();
3380 MCSection *ReadOnlySection = getContext().getELFSection(
3381 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3382
3383 MCSymbol *Sym = getContext().createTempSymbol();
3384 const MCExpr *LoSym =
3385 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3386 const MipsMCExpr *LoExpr =
3387 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3388
3389 getStreamer().SwitchSection(ReadOnlySection);
3390 getStreamer().EmitLabel(Sym, IDLoc);
3391 getStreamer().EmitIntValue(HiImmOp64, 4);
3392 getStreamer().EmitIntValue(LoImmOp64, 4);
3393 getStreamer().SwitchSection(CS);
3394
3395 if(emitPartialAddress(TOut, IDLoc, Sym))
3396 return true;
3397 if(isABI_N64())
3398 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3399 MCOperand::createExpr(LoExpr), IDLoc, STI);
3400 else
3401 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3402 MCOperand::createExpr(LoExpr), IDLoc, STI);
3403
3404 if(isABI_N32() || isABI_N64())
3405 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3406 else {
3407 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3408 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3409 }
3410 return false;
3411 } else { // if(!IsGPR && !IsSingle)
3412 if ((LoImmOp64 == 0) &&
3413 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3414 // FIXME: In the case where the constant is zero, we can load the
3415 // register directly from the zero register.
3416 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3417 Out, STI))
3418 return true;
3419 if (isABI_N32() || isABI_N64())
3420 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3421 else if (hasMips32r2()) {
3422 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3423 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3424 } else {
3425 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3426 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3427 }
3428 return false;
3429 }
3430
3431 MCSection *CS = getStreamer().getCurrentSectionOnly();
3432 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3433 // where appropriate.
3434 MCSection *ReadOnlySection = getContext().getELFSection(
3435 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3436
3437 MCSymbol *Sym = getContext().createTempSymbol();
3438 const MCExpr *LoSym =
3439 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3440 const MipsMCExpr *LoExpr =
3441 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3442
3443 getStreamer().SwitchSection(ReadOnlySection);
3444 getStreamer().EmitLabel(Sym, IDLoc);
3445 getStreamer().EmitIntValue(HiImmOp64, 4);
3446 getStreamer().EmitIntValue(LoImmOp64, 4);
3447 getStreamer().SwitchSection(CS);
3448
3449 if(emitPartialAddress(TOut, IDLoc, Sym))
3450 return true;
3451 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3452 MCOperand::createExpr(LoExpr), IDLoc, STI);
3453 }
3454 return false;
3455}
3456
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003457bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3458 MCStreamer &Out,
3459 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003460 MipsTargetStreamer &TOut = getTargetStreamer();
3461
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003462 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3463 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003464
3465 MCOperand Offset = Inst.getOperand(0);
3466 if (Offset.isExpr()) {
3467 Inst.clear();
3468 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003469 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3470 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3471 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003472 } else {
3473 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003474 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003475 // If offset fits into 11 bits then this instruction becomes microMIPS
3476 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003477 if (inMicroMipsMode())
3478 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003479 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003480 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003481 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003482 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003483 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003484 Inst.clear();
3485 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003486 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3487 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3488 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003489 }
3490 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003491 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003492
Zoran Jovanovicada70912015-09-07 11:56:37 +00003493 // If .set reorder is active and branch instruction has a delay slot,
3494 // emit a NOP after it.
3495 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3496 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003497 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003498
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003499 return false;
3500}
3501
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003502bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3503 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003504 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003505 const MCOperand &DstRegOp = Inst.getOperand(0);
3506 assert(DstRegOp.isReg() && "expected register operand kind");
3507
3508 const MCOperand &ImmOp = Inst.getOperand(1);
3509 assert(ImmOp.isImm() && "expected immediate operand kind");
3510
3511 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003512 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3513 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003514
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003515 bool IsLikely = false;
3516
Toma Tabacue1e460d2015-06-11 10:36:10 +00003517 unsigned OpCode = 0;
3518 switch(Inst.getOpcode()) {
3519 case Mips::BneImm:
3520 OpCode = Mips::BNE;
3521 break;
3522 case Mips::BeqImm:
3523 OpCode = Mips::BEQ;
3524 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003525 case Mips::BEQLImmMacro:
3526 OpCode = Mips::BEQL;
3527 IsLikely = true;
3528 break;
3529 case Mips::BNELImmMacro:
3530 OpCode = Mips::BNEL;
3531 IsLikely = true;
3532 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003533 default:
3534 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3535 break;
3536 }
3537
3538 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003539 if (ImmValue == 0) {
3540 if (IsLikely) {
3541 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3542 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3543 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3544 } else
3545 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3546 STI);
3547 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003548 warnIfNoMacro(IDLoc);
3549
3550 unsigned ATReg = getATReg(IDLoc);
3551 if (!ATReg)
3552 return true;
3553
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003554 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003555 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003556 return true;
3557
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003558 if (IsLikely) {
3559 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3560 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3561 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3562 } else
3563 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003564 }
3565 return false;
3566}
3567
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003568void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Simon Atanasyana1882672018-05-24 07:36:11 +00003569 const MCSubtargetInfo *STI, bool IsLoad) {
Simon Atanasyanbe8a42e2018-05-24 07:36:06 +00003570 const MCOperand &DstRegOp = Inst.getOperand(0);
3571 assert(DstRegOp.isReg() && "expected register operand kind");
3572 const MCOperand &BaseRegOp = Inst.getOperand(1);
3573 assert(BaseRegOp.isReg() && "expected register operand kind");
3574 const MCOperand &OffsetOp = Inst.getOperand(2);
Daniel Sandersfba875f2016-04-29 13:43:45 +00003575
Simon Atanasyanbe8a42e2018-05-24 07:36:06 +00003576 MipsTargetStreamer &TOut = getTargetStreamer();
3577 unsigned DstReg = DstRegOp.getReg();
3578 unsigned BaseReg = BaseRegOp.getReg();
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003579 unsigned TmpReg = DstReg;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003580
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003581 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003582 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3583 unsigned DstRegClassID =
3584 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3585 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3586 (DstRegClassID == Mips::GPR64RegClassID);
3587
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00003588 if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003589 // At this point we need AT to perform the expansions
3590 // and we exit if it is not available.
3591 TmpReg = getATReg(IDLoc);
3592 if (!TmpReg)
3593 return;
3594 }
3595
Simon Atanasyana1882672018-05-24 07:36:11 +00003596 if (OffsetOp.isImm()) {
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00003597 int64_t LoOffset = OffsetOp.getImm() & 0xffff;
3598 int64_t HiOffset = OffsetOp.getImm() & ~0xffff;
3599
3600 // If msb of LoOffset is 1(negative number) we must increment
3601 // HiOffset to account for the sign-extension of the low part.
3602 if (LoOffset & 0x8000)
3603 HiOffset += 0x10000;
3604
3605 bool IsLargeOffset = HiOffset != 0;
3606
3607 if (IsLargeOffset) {
3608 bool Is32BitImm = (HiOffset >> 32) == 0;
3609 if (loadImmediate(HiOffset, TmpReg, Mips::NoRegister, Is32BitImm, true,
3610 IDLoc, Out, STI))
3611 return;
3612 }
3613
3614 if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)
3615 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg,
3616 BaseReg, IDLoc, STI);
3617 TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, LoOffset, IDLoc, STI);
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003618 } else {
3619 assert(OffsetOp.isExpr() && "expected expression operand kind");
3620 const MCExpr *ExprOffset = OffsetOp.getExpr();
3621 MCOperand LoOperand = MCOperand::createExpr(
3622 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3623 MCOperand HiOperand = MCOperand::createExpr(
3624 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00003625
3626 if (IsLoad)
3627 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3628 LoOperand, TmpReg, IDLoc, STI);
3629 else
3630 TOut.emitStoreWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3631 LoOperand, TmpReg, IDLoc, STI);
Daniel Sandersfba875f2016-04-29 13:43:45 +00003632 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003633}
3634
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003635bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3636 MCStreamer &Out,
3637 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003638 unsigned OpNum = Inst.getNumOperands();
3639 unsigned Opcode = Inst.getOpcode();
3640 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3641
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003642 assert(Inst.getOperand(OpNum - 1).isImm() &&
3643 Inst.getOperand(OpNum - 2).isReg() &&
3644 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003645
3646 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3647 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003648 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3649 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3650 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3651 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003652 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003653 if (inMicroMipsMode() && hasMips32r6())
3654 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3655 else
3656 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3657 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003658
3659 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003660 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003661 return false;
3662}
3663
Toma Tabacu1a108322015-06-17 13:20:24 +00003664bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003665 MCStreamer &Out,
3666 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003667 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003668 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003669 unsigned PseudoOpcode = Inst.getOpcode();
3670 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003671 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003672 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3673
3674 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003675 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003676
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003677 unsigned TrgReg;
3678 if (TrgOp.isReg())
3679 TrgReg = TrgOp.getReg();
3680 else if (TrgOp.isImm()) {
3681 warnIfNoMacro(IDLoc);
3682 EmittedNoMacroWarning = true;
3683
3684 TrgReg = getATReg(IDLoc);
3685 if (!TrgReg)
3686 return true;
3687
3688 switch(PseudoOpcode) {
3689 default:
3690 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3691 case Mips::BLTImmMacro:
3692 PseudoOpcode = Mips::BLT;
3693 break;
3694 case Mips::BLEImmMacro:
3695 PseudoOpcode = Mips::BLE;
3696 break;
3697 case Mips::BGEImmMacro:
3698 PseudoOpcode = Mips::BGE;
3699 break;
3700 case Mips::BGTImmMacro:
3701 PseudoOpcode = Mips::BGT;
3702 break;
3703 case Mips::BLTUImmMacro:
3704 PseudoOpcode = Mips::BLTU;
3705 break;
3706 case Mips::BLEUImmMacro:
3707 PseudoOpcode = Mips::BLEU;
3708 break;
3709 case Mips::BGEUImmMacro:
3710 PseudoOpcode = Mips::BGEU;
3711 break;
3712 case Mips::BGTUImmMacro:
3713 PseudoOpcode = Mips::BGTU;
3714 break;
3715 case Mips::BLTLImmMacro:
3716 PseudoOpcode = Mips::BLTL;
3717 break;
3718 case Mips::BLELImmMacro:
3719 PseudoOpcode = Mips::BLEL;
3720 break;
3721 case Mips::BGELImmMacro:
3722 PseudoOpcode = Mips::BGEL;
3723 break;
3724 case Mips::BGTLImmMacro:
3725 PseudoOpcode = Mips::BGTL;
3726 break;
3727 case Mips::BLTULImmMacro:
3728 PseudoOpcode = Mips::BLTUL;
3729 break;
3730 case Mips::BLEULImmMacro:
3731 PseudoOpcode = Mips::BLEUL;
3732 break;
3733 case Mips::BGEULImmMacro:
3734 PseudoOpcode = Mips::BGEUL;
3735 break;
3736 case Mips::BGTULImmMacro:
3737 PseudoOpcode = Mips::BGTUL;
3738 break;
3739 }
3740
3741 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003742 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003743 return true;
3744 }
3745
Toma Tabacu1a108322015-06-17 13:20:24 +00003746 switch (PseudoOpcode) {
3747 case Mips::BLT:
3748 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003749 case Mips::BLTL:
3750 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003751 AcceptsEquality = false;
3752 ReverseOrderSLT = false;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003753 IsUnsigned =
3754 ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003755 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003756 ZeroSrcOpcode = Mips::BGTZ;
3757 ZeroTrgOpcode = Mips::BLTZ;
3758 break;
3759 case Mips::BLE:
3760 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003761 case Mips::BLEL:
3762 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003763 AcceptsEquality = true;
3764 ReverseOrderSLT = true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003765 IsUnsigned =
3766 ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003767 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003768 ZeroSrcOpcode = Mips::BGEZ;
3769 ZeroTrgOpcode = Mips::BLEZ;
3770 break;
3771 case Mips::BGE:
3772 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003773 case Mips::BGEL:
3774 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003775 AcceptsEquality = true;
3776 ReverseOrderSLT = false;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003777 IsUnsigned =
3778 ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003779 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003780 ZeroSrcOpcode = Mips::BLEZ;
3781 ZeroTrgOpcode = Mips::BGEZ;
3782 break;
3783 case Mips::BGT:
3784 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003785 case Mips::BGTL:
3786 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003787 AcceptsEquality = false;
3788 ReverseOrderSLT = true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003789 IsUnsigned =
3790 ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003791 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003792 ZeroSrcOpcode = Mips::BLTZ;
3793 ZeroTrgOpcode = Mips::BGTZ;
3794 break;
3795 default:
3796 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3797 }
3798
Toma Tabacu1a108322015-06-17 13:20:24 +00003799 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3800 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3801 if (IsSrcRegZero && IsTrgRegZero) {
3802 // FIXME: All of these Opcode-specific if's are needed for compatibility
3803 // with GAS' behaviour. However, they may not generate the most efficient
3804 // code in some circumstances.
3805 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003806 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3807 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003808 return false;
3809 }
3810 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003811 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3812 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003813 Warning(IDLoc, "branch is always taken");
3814 return false;
3815 }
3816 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003817 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3818 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003819 Warning(IDLoc, "branch is always taken");
3820 return false;
3821 }
3822 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003823 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3824 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003825 return false;
3826 }
3827 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003828 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3829 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003830 return false;
3831 }
3832 if (AcceptsEquality) {
3833 // If both registers are $0 and the pseudo-branch accepts equality, it
3834 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003835 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3836 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003837 Warning(IDLoc, "branch is always taken");
3838 return false;
3839 }
3840 // If both registers are $0 and the pseudo-branch does not accept
3841 // equality, it will never be taken, so we don't have to emit anything.
3842 return false;
3843 }
3844 if (IsSrcRegZero || IsTrgRegZero) {
3845 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3846 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3847 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3848 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3849 // the pseudo-branch will never be taken, so we don't emit anything.
3850 // This only applies to unsigned pseudo-branches.
3851 return false;
3852 }
3853 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3854 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3855 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3856 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3857 // the pseudo-branch will always be taken, so we emit an unconditional
3858 // branch.
3859 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003860 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3861 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003862 Warning(IDLoc, "branch is always taken");
3863 return false;
3864 }
3865 if (IsUnsigned) {
3866 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3867 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3868 // the pseudo-branch will be taken only when the non-zero register is
3869 // different from 0, so we emit a BNEZ.
3870 //
3871 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3872 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3873 // the pseudo-branch will be taken only when the non-zero register is
3874 // equal to 0, so we emit a BEQZ.
3875 //
3876 // Because only BLEU and BGEU branch on equality, we can use the
3877 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003878 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3879 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3880 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003881 return false;
3882 }
3883 // If we have a signed pseudo-branch and one of the registers is $0,
3884 // we can use an appropriate compare-to-zero branch. We select which one
3885 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003886 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3887 IsSrcRegZero ? TrgReg : SrcReg,
3888 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003889 return false;
3890 }
3891
3892 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3893 // expansions. If it is not available, we return.
3894 unsigned ATRegNum = getATReg(IDLoc);
3895 if (!ATRegNum)
3896 return true;
3897
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003898 if (!EmittedNoMacroWarning)
3899 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003900
3901 // SLT fits well with 2 of our 4 pseudo-branches:
3902 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3903 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3904 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3905 // This is accomplished by using a BNEZ with the result of the SLT.
3906 //
3907 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
Hiroshi Inoue7f9f92f2018-02-22 07:48:29 +00003908 // and BLE with BGT), so we change the BNEZ into a BEQZ.
Toma Tabacu1a108322015-06-17 13:20:24 +00003909 // Because only BGE and BLE branch on equality, we can use the
3910 // AcceptsEquality variable to decide when to emit the BEQZ.
3911 // Note that the order of the SLT arguments doesn't change between
3912 // opposites.
3913 //
3914 // The same applies to the unsigned variants, except that SLTu is used
3915 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003916 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3917 ReverseOrderSLT ? TrgReg : SrcReg,
3918 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003919
Daniel Sandersa736b372016-04-29 13:33:12 +00003920 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3921 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3922 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3923 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003924 return false;
3925}
3926
Simon Dardis509da1a2017-02-13 16:06:48 +00003927// Expand a integer division macro.
3928//
3929// Notably we don't have to emit a warning when encountering $rt as the $zero
3930// register, or 0 as an immediate. processInstruction() has already done that.
3931//
3932// The destination register can only be $zero when expanding (S)DivIMacro or
3933// D(S)DivMacro.
3934
Stefan Maksimovic0a239982018-07-09 13:06:44 +00003935bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3936 const MCSubtargetInfo *STI, const bool IsMips64,
3937 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003938 MipsTargetStreamer &TOut = getTargetStreamer();
3939
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003940 warnIfNoMacro(IDLoc);
3941
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003942 const MCOperand &RdRegOp = Inst.getOperand(0);
3943 assert(RdRegOp.isReg() && "expected register operand kind");
3944 unsigned RdReg = RdRegOp.getReg();
3945
3946 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003947 assert(RsRegOp.isReg() && "expected register operand kind");
3948 unsigned RsReg = RsRegOp.getReg();
3949
Simon Dardis12850ee2017-01-31 10:49:24 +00003950 unsigned RtReg;
3951 int64_t ImmValue;
3952
3953 const MCOperand &RtOp = Inst.getOperand(2);
3954 assert((RtOp.isReg() || RtOp.isImm()) &&
3955 "expected register or immediate operand kind");
3956 if (RtOp.isReg())
3957 RtReg = RtOp.getReg();
3958 else
3959 ImmValue = RtOp.getImm();
3960
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003961 unsigned DivOp;
3962 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003963 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003964
3965 if (IsMips64) {
3966 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3967 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003968 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003969 } else {
3970 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3971 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003972 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003973 }
3974
3975 bool UseTraps = useTraps();
3976
Stefan Maksimovic0a239982018-07-09 13:06:44 +00003977 unsigned Opcode = Inst.getOpcode();
3978 bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro ||
3979 Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro ||
3980 Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro ||
3981 Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro;
3982
3983 bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro ||
3984 Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro ||
3985 Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro ||
3986 Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro;
3987
Simon Dardis12850ee2017-01-31 10:49:24 +00003988 if (RtOp.isImm()) {
3989 unsigned ATReg = getATReg(IDLoc);
3990 if (!ATReg)
3991 return true;
3992
3993 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003994 if (UseTraps)
3995 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3996 else
3997 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3998 return false;
3999 }
4000
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004001 if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1)))) {
4002 TOut.emitRRR(Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI);
4003 return false;
4004 } else if (isDiv && ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004005 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00004006 return false;
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004007 } else if (isDiv && Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004008 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00004009 return false;
4010 } else {
4011 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
4012 false, Inst.getLoc(), Out, STI))
4013 return true;
4014 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004015 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00004016 return false;
4017 }
4018 return true;
4019 }
4020
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004021 // If the macro expansion of (d)div(u) or (d)rem(u) would always trap or
4022 // break, insert the trap/break and exit. This gives a different result to
4023 // GAS. GAS has an inconsistency/missed optimization in that not all cases
4024 // are handled equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004025 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004026 if (UseTraps) {
4027 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004028 return false;
4029 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004030 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4031 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004032 }
4033
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004034 // (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does
4035 // not expand to macro sequence.
4036 if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) {
4037 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
4038 return false;
4039 }
4040
Simon Dardis509da1a2017-02-13 16:06:48 +00004041 // Temporary label for first branch traget
4042 MCContext &Context = TOut.getStreamer().getContext();
4043 MCSymbol *BrTarget;
4044 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004045
4046 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004047 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004048 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004049 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004050 BrTarget = Context.createTempSymbol();
4051 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4052 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004053 }
4054
Daniel Sandersa736b372016-04-29 13:33:12 +00004055 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004056
4057 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004058 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004059
4060 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004061 if (!UseTraps)
4062 TOut.getStreamer().EmitLabel(BrTarget);
4063
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004064 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004065 return false;
4066 }
4067
4068 unsigned ATReg = getATReg(IDLoc);
4069 if (!ATReg)
4070 return true;
4071
Simon Dardis509da1a2017-02-13 16:06:48 +00004072 if (!UseTraps)
4073 TOut.getStreamer().EmitLabel(BrTarget);
4074
Daniel Sandersa736b372016-04-29 13:33:12 +00004075 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004076
4077 // Temporary label for the second branch target.
4078 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4079 MCOperand LabelOpEnd =
4080 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4081
4082 // Branch to the mflo instruction.
4083 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4084
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004085 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004086 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004087 TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004088 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004089 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004090 }
4091
4092 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004093 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004094 else {
4095 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004096 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004097 TOut.emitNop(IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004098 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004099 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004100
4101 TOut.getStreamer().EmitLabel(BrTargetEnd);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004102 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004103 return false;
4104}
4105
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004106bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004107 SMLoc IDLoc, MCStreamer &Out,
4108 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004109 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004110
4111 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4112 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4113 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4114
4115 unsigned FirstReg = Inst.getOperand(0).getReg();
4116 unsigned SecondReg = Inst.getOperand(1).getReg();
4117 unsigned ThirdReg = Inst.getOperand(2).getReg();
4118
4119 if (hasMips1() && !hasMips2()) {
4120 unsigned ATReg = getATReg(IDLoc);
4121 if (!ATReg)
4122 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004123 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4124 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4125 TOut.emitNop(IDLoc, STI);
4126 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4127 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4128 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4129 TOut.emitNop(IDLoc, STI);
4130 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4131 : Mips::CVT_W_S,
4132 FirstReg, SecondReg, IDLoc, STI);
4133 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4134 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004135 return false;
4136 }
4137
Daniel Sandersa736b372016-04-29 13:33:12 +00004138 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4139 : Mips::TRUNC_W_S,
4140 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004141
4142 return false;
4143}
4144
Daniel Sanders6394ee52015-10-15 14:52:58 +00004145bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004146 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004147 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004148 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004149 }
4150
Toma Tabacud88d79c2015-06-23 14:39:42 +00004151 const MCOperand &DstRegOp = Inst.getOperand(0);
4152 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004153 const MCOperand &SrcRegOp = Inst.getOperand(1);
4154 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004155 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4156 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4157
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004158 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004159 unsigned DstReg = DstRegOp.getReg();
4160 unsigned SrcReg = SrcRegOp.getReg();
4161 int64_t OffsetValue = OffsetImmOp.getImm();
4162
4163 // NOTE: We always need AT for ULHU, as it is always used as the source
4164 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004165 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004166 unsigned ATReg = getATReg(IDLoc);
4167 if (!ATReg)
4168 return true;
4169
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004170 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4171 if (IsLargeOffset) {
4172 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4173 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004174 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004175 }
4176
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004177 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4178 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4179 if (isLittle())
4180 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004181
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004182 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4183 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004184
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004185 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4186 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004187
Daniel Sandersa736b372016-04-29 13:33:12 +00004188 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004189 FirstOffset, IDLoc, STI);
4190 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004191 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004192 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004193
4194 return false;
4195}
4196
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004197bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004198 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004199 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004200 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004201 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004202
4203 const MCOperand &DstRegOp = Inst.getOperand(0);
4204 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004205 const MCOperand &SrcRegOp = Inst.getOperand(1);
4206 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004207 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4208 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4209
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004210 MipsTargetStreamer &TOut = getTargetStreamer();
4211 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004212 unsigned SrcReg = SrcRegOp.getReg();
4213 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004214
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004215 warnIfNoMacro(IDLoc);
4216 unsigned ATReg = getATReg(IDLoc);
4217 if (!ATReg)
4218 return true;
4219
4220 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4221 if (IsLargeOffset) {
4222 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4223 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004224 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004225 }
4226
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004227 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4228 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4229 if (isLittle())
4230 std::swap(FirstOffset, SecondOffset);
4231
4232 if (IsLargeOffset) {
4233 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4234 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4235 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4236 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4237 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4238 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004239 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004240 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4241 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4242 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004243 }
4244
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004245 return false;
4246}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004247
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004248bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4249 const MCSubtargetInfo *STI) {
4250 if (hasMips32r6() || hasMips64r6()) {
4251 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4252 }
4253
4254 const MCOperand &DstRegOp = Inst.getOperand(0);
4255 assert(DstRegOp.isReg() && "expected register operand kind");
4256 const MCOperand &SrcRegOp = Inst.getOperand(1);
4257 assert(SrcRegOp.isReg() && "expected register operand kind");
4258 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4259 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4260
4261 MipsTargetStreamer &TOut = getTargetStreamer();
4262 unsigned DstReg = DstRegOp.getReg();
4263 unsigned SrcReg = SrcRegOp.getReg();
4264 int64_t OffsetValue = OffsetImmOp.getImm();
4265
4266 // Compute left/right load/store offsets.
4267 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4268 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4269 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4270 if (isLittle())
4271 std::swap(LxlOffset, LxrOffset);
4272
4273 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4274 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4275 unsigned TmpReg = SrcReg;
4276 if (IsLargeOffset || DoMove) {
4277 warnIfNoMacro(IDLoc);
4278 TmpReg = getATReg(IDLoc);
4279 if (!TmpReg)
4280 return true;
4281 }
4282
4283 if (IsLargeOffset) {
4284 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4285 IDLoc, Out, STI))
4286 return true;
4287 }
4288
4289 if (DoMove)
4290 std::swap(DstReg, TmpReg);
4291
4292 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4293 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4294 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4295 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4296
4297 if (DoMove)
4298 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004299
4300 return false;
4301}
4302
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004303bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004304 MCStreamer &Out,
4305 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004306 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004307
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004308 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4309 assert(Inst.getOperand(0).isReg() &&
4310 Inst.getOperand(1).isReg() &&
4311 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004312
4313 unsigned ATReg = Mips::NoRegister;
4314 unsigned FinalDstReg = Mips::NoRegister;
4315 unsigned DstReg = Inst.getOperand(0).getReg();
4316 unsigned SrcReg = Inst.getOperand(1).getReg();
4317 int64_t ImmValue = Inst.getOperand(2).getImm();
4318
Simon Dardisaa208812017-02-24 14:34:32 +00004319 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004320
4321 unsigned FinalOpcode = Inst.getOpcode();
4322
4323 if (DstReg == SrcReg) {
4324 ATReg = getATReg(Inst.getLoc());
4325 if (!ATReg)
4326 return true;
4327 FinalDstReg = DstReg;
4328 DstReg = ATReg;
4329 }
4330
Simon Atanasyan478220f2018-05-24 07:36:00 +00004331 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false,
4332 Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004333 switch (FinalOpcode) {
4334 default:
4335 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004336 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004337 FinalOpcode = Mips::ADD;
4338 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004339 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004340 FinalOpcode = Mips::ADDu;
4341 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004342 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004343 FinalOpcode = Mips::AND;
4344 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004345 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004346 FinalOpcode = Mips::NOR;
4347 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004348 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004349 FinalOpcode = Mips::OR;
4350 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004351 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004352 FinalOpcode = Mips::SLT;
4353 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004354 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004355 FinalOpcode = Mips::SLTu;
4356 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004357 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004358 FinalOpcode = Mips::XOR;
4359 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004360 case Mips::ADDi_MM:
4361 FinalOpcode = Mips::ADD_MM;
4362 break;
4363 case Mips::ADDiu_MM:
4364 FinalOpcode = Mips::ADDu_MM;
4365 break;
4366 case Mips::ANDi_MM:
4367 FinalOpcode = Mips::AND_MM;
4368 break;
4369 case Mips::ORi_MM:
4370 FinalOpcode = Mips::OR_MM;
4371 break;
4372 case Mips::SLTi_MM:
4373 FinalOpcode = Mips::SLT_MM;
4374 break;
4375 case Mips::SLTiu_MM:
4376 FinalOpcode = Mips::SLTu_MM;
4377 break;
4378 case Mips::XORi_MM:
4379 FinalOpcode = Mips::XOR_MM;
4380 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004381 case Mips::ANDi64:
4382 FinalOpcode = Mips::AND64;
4383 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004384 case Mips::NORImm64:
4385 FinalOpcode = Mips::NOR64;
4386 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004387 case Mips::ORi64:
4388 FinalOpcode = Mips::OR64;
4389 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004390 case Mips::SLTImm64:
4391 FinalOpcode = Mips::SLT64;
4392 break;
4393 case Mips::SLTUImm64:
4394 FinalOpcode = Mips::SLTu64;
4395 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004396 case Mips::XORi64:
4397 FinalOpcode = Mips::XOR64;
4398 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004399 }
4400
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004401 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004402 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004403 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004404 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004405 return false;
4406 }
4407 return true;
4408}
4409
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004410bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4411 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004412 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004413 unsigned ATReg = Mips::NoRegister;
4414 unsigned DReg = Inst.getOperand(0).getReg();
4415 unsigned SReg = Inst.getOperand(1).getReg();
4416 unsigned TReg = Inst.getOperand(2).getReg();
4417 unsigned TmpReg = DReg;
4418
4419 unsigned FirstShift = Mips::NOP;
4420 unsigned SecondShift = Mips::NOP;
4421
4422 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004423 if (DReg == SReg) {
4424 TmpReg = getATReg(Inst.getLoc());
4425 if (!TmpReg)
4426 return true;
4427 }
4428
4429 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004430 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4431 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004432 return false;
4433 }
4434
4435 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004436 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004437 return false;
4438 }
4439
4440 return true;
4441 }
4442
4443 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004444 switch (Inst.getOpcode()) {
4445 default:
4446 llvm_unreachable("unexpected instruction opcode");
4447 case Mips::ROL:
4448 FirstShift = Mips::SRLV;
4449 SecondShift = Mips::SLLV;
4450 break;
4451 case Mips::ROR:
4452 FirstShift = Mips::SLLV;
4453 SecondShift = Mips::SRLV;
4454 break;
4455 }
4456
4457 ATReg = getATReg(Inst.getLoc());
4458 if (!ATReg)
4459 return true;
4460
Daniel Sandersa736b372016-04-29 13:33:12 +00004461 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4462 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4463 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4464 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004465
4466 return false;
4467 }
4468
4469 return true;
4470}
4471
4472bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004473 MCStreamer &Out,
4474 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004475 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004476 unsigned ATReg = Mips::NoRegister;
4477 unsigned DReg = Inst.getOperand(0).getReg();
4478 unsigned SReg = Inst.getOperand(1).getReg();
4479 int64_t ImmValue = Inst.getOperand(2).getImm();
4480
4481 unsigned FirstShift = Mips::NOP;
4482 unsigned SecondShift = Mips::NOP;
4483
4484 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004485 if (Inst.getOpcode() == Mips::ROLImm) {
4486 uint64_t MaxShift = 32;
4487 uint64_t ShiftValue = ImmValue;
4488 if (ImmValue != 0)
4489 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004490 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004491 return false;
4492 }
4493
4494 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004495 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004496 return false;
4497 }
4498
4499 return true;
4500 }
4501
4502 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004503 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004504 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004505 return false;
4506 }
4507
4508 switch (Inst.getOpcode()) {
4509 default:
4510 llvm_unreachable("unexpected instruction opcode");
4511 case Mips::ROLImm:
4512 FirstShift = Mips::SLL;
4513 SecondShift = Mips::SRL;
4514 break;
4515 case Mips::RORImm:
4516 FirstShift = Mips::SRL;
4517 SecondShift = Mips::SLL;
4518 break;
4519 }
4520
4521 ATReg = getATReg(Inst.getLoc());
4522 if (!ATReg)
4523 return true;
4524
Daniel Sandersa736b372016-04-29 13:33:12 +00004525 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4526 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4527 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004528
4529 return false;
4530 }
4531
4532 return true;
4533}
4534
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004535bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4536 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004537 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004538 unsigned ATReg = Mips::NoRegister;
4539 unsigned DReg = Inst.getOperand(0).getReg();
4540 unsigned SReg = Inst.getOperand(1).getReg();
4541 unsigned TReg = Inst.getOperand(2).getReg();
4542 unsigned TmpReg = DReg;
4543
4544 unsigned FirstShift = Mips::NOP;
4545 unsigned SecondShift = Mips::NOP;
4546
4547 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004548 if (TmpReg == SReg) {
4549 TmpReg = getATReg(Inst.getLoc());
4550 if (!TmpReg)
4551 return true;
4552 }
4553
4554 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004555 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4556 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004557 return false;
4558 }
4559
4560 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004561 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004562 return false;
4563 }
4564
4565 return true;
4566 }
4567
4568 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004569 switch (Inst.getOpcode()) {
4570 default:
4571 llvm_unreachable("unexpected instruction opcode");
4572 case Mips::DROL:
4573 FirstShift = Mips::DSRLV;
4574 SecondShift = Mips::DSLLV;
4575 break;
4576 case Mips::DROR:
4577 FirstShift = Mips::DSLLV;
4578 SecondShift = Mips::DSRLV;
4579 break;
4580 }
4581
4582 ATReg = getATReg(Inst.getLoc());
4583 if (!ATReg)
4584 return true;
4585
Daniel Sandersa736b372016-04-29 13:33:12 +00004586 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4587 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4588 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4589 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004590
4591 return false;
4592 }
4593
4594 return true;
4595}
4596
4597bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004598 MCStreamer &Out,
4599 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004600 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004601 unsigned ATReg = Mips::NoRegister;
4602 unsigned DReg = Inst.getOperand(0).getReg();
4603 unsigned SReg = Inst.getOperand(1).getReg();
4604 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4605
4606 unsigned FirstShift = Mips::NOP;
4607 unsigned SecondShift = Mips::NOP;
4608
4609 MCInst TmpInst;
4610
4611 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004612 unsigned FinalOpcode = Mips::NOP;
4613 if (ImmValue == 0)
4614 FinalOpcode = Mips::DROTR;
4615 else if (ImmValue % 32 == 0)
4616 FinalOpcode = Mips::DROTR32;
4617 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4618 if (Inst.getOpcode() == Mips::DROLImm)
4619 FinalOpcode = Mips::DROTR32;
4620 else
4621 FinalOpcode = Mips::DROTR;
4622 } else if (ImmValue >= 33) {
4623 if (Inst.getOpcode() == Mips::DROLImm)
4624 FinalOpcode = Mips::DROTR;
4625 else
4626 FinalOpcode = Mips::DROTR32;
4627 }
4628
4629 uint64_t ShiftValue = ImmValue % 32;
4630 if (Inst.getOpcode() == Mips::DROLImm)
4631 ShiftValue = (32 - ImmValue % 32) % 32;
4632
Daniel Sandersa736b372016-04-29 13:33:12 +00004633 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004634
4635 return false;
4636 }
4637
4638 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004639 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004640 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004641 return false;
4642 }
4643
4644 switch (Inst.getOpcode()) {
4645 default:
4646 llvm_unreachable("unexpected instruction opcode");
4647 case Mips::DROLImm:
4648 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4649 FirstShift = Mips::DSLL;
4650 SecondShift = Mips::DSRL32;
4651 }
4652 if (ImmValue == 32) {
4653 FirstShift = Mips::DSLL32;
4654 SecondShift = Mips::DSRL32;
4655 }
4656 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4657 FirstShift = Mips::DSLL32;
4658 SecondShift = Mips::DSRL;
4659 }
4660 break;
4661 case Mips::DRORImm:
4662 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4663 FirstShift = Mips::DSRL;
4664 SecondShift = Mips::DSLL32;
4665 }
4666 if (ImmValue == 32) {
4667 FirstShift = Mips::DSRL32;
4668 SecondShift = Mips::DSLL32;
4669 }
4670 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4671 FirstShift = Mips::DSRL32;
4672 SecondShift = Mips::DSLL;
4673 }
4674 break;
4675 }
4676
4677 ATReg = getATReg(Inst.getLoc());
4678 if (!ATReg)
4679 return true;
4680
Daniel Sandersa736b372016-04-29 13:33:12 +00004681 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4682 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4683 Inst.getLoc(), STI);
4684 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004685
4686 return false;
4687 }
4688
4689 return true;
4690}
4691
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004692bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4693 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004694 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004695 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4696 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4697
Daniel Sandersa736b372016-04-29 13:33:12 +00004698 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004699 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004700 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004701 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004702 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4703 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004704
4705 return false;
4706}
4707
Simon Dardis3c82a642017-02-08 16:25:05 +00004708bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4709 const MCSubtargetInfo *STI) {
4710 MipsTargetStreamer &TOut = getTargetStreamer();
4711 unsigned ATReg = Mips::NoRegister;
4712 unsigned DstReg = Inst.getOperand(0).getReg();
4713 unsigned SrcReg = Inst.getOperand(1).getReg();
4714 int32_t ImmValue = Inst.getOperand(2).getImm();
4715
4716 ATReg = getATReg(IDLoc);
4717 if (!ATReg)
4718 return true;
4719
Simon Atanasyan478220f2018-05-24 07:36:00 +00004720 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out,
4721 STI);
Simon Dardis3c82a642017-02-08 16:25:05 +00004722
4723 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4724 SrcReg, ATReg, IDLoc, STI);
4725
4726 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4727
4728 return false;
4729}
4730
4731bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4732 const MCSubtargetInfo *STI) {
4733 MipsTargetStreamer &TOut = getTargetStreamer();
4734 unsigned ATReg = Mips::NoRegister;
4735 unsigned DstReg = Inst.getOperand(0).getReg();
4736 unsigned SrcReg = Inst.getOperand(1).getReg();
4737 unsigned TmpReg = Inst.getOperand(2).getReg();
4738
4739 ATReg = getATReg(Inst.getLoc());
4740 if (!ATReg)
4741 return true;
4742
4743 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4744 SrcReg, TmpReg, IDLoc, STI);
4745
4746 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4747
4748 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4749 DstReg, DstReg, 0x1F, IDLoc, STI);
4750
4751 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4752
4753 if (useTraps()) {
4754 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4755 } else {
4756 MCContext & Context = TOut.getStreamer().getContext();
4757 MCSymbol * BrTarget = Context.createTempSymbol();
4758 MCOperand LabelOp =
4759 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4760
4761 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4762 if (AssemblerOptions.back()->isReorder())
4763 TOut.emitNop(IDLoc, STI);
4764 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4765
4766 TOut.getStreamer().EmitLabel(BrTarget);
4767 }
4768 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4769
4770 return false;
4771}
4772
4773bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4774 const MCSubtargetInfo *STI) {
4775 MipsTargetStreamer &TOut = getTargetStreamer();
4776 unsigned ATReg = Mips::NoRegister;
4777 unsigned DstReg = Inst.getOperand(0).getReg();
4778 unsigned SrcReg = Inst.getOperand(1).getReg();
4779 unsigned TmpReg = Inst.getOperand(2).getReg();
4780
4781 ATReg = getATReg(IDLoc);
4782 if (!ATReg)
4783 return true;
4784
4785 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4786 SrcReg, TmpReg, IDLoc, STI);
4787
4788 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4789 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4790 if (useTraps()) {
4791 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4792 } else {
4793 MCContext & Context = TOut.getStreamer().getContext();
4794 MCSymbol * BrTarget = Context.createTempSymbol();
4795 MCOperand LabelOp =
4796 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4797
4798 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4799 if (AssemblerOptions.back()->isReorder())
4800 TOut.emitNop(IDLoc, STI);
4801 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4802
4803 TOut.getStreamer().EmitLabel(BrTarget);
4804 }
4805
4806 return false;
4807}
4808
4809bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4810 const MCSubtargetInfo *STI) {
4811 MipsTargetStreamer &TOut = getTargetStreamer();
4812 unsigned DstReg = Inst.getOperand(0).getReg();
4813 unsigned SrcReg = Inst.getOperand(1).getReg();
4814 unsigned TmpReg = Inst.getOperand(2).getReg();
4815
4816 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4817 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4818
4819 return false;
4820}
4821
Simon Dardisaff4d142016-10-18 14:28:00 +00004822// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4823// lw $<reg+1>>, offset+4($reg2)'
4824// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4825// sw $<reg+1>>, offset+4($reg2)'
4826// for O32.
4827bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4828 MCStreamer &Out,
4829 const MCSubtargetInfo *STI,
4830 bool IsLoad) {
4831 if (!isABI_O32())
4832 return true;
4833
4834 warnIfNoMacro(IDLoc);
4835
4836 MipsTargetStreamer &TOut = getTargetStreamer();
4837 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4838 unsigned FirstReg = Inst.getOperand(0).getReg();
4839 unsigned SecondReg = nextReg(FirstReg);
4840 unsigned BaseReg = Inst.getOperand(1).getReg();
4841 if (!SecondReg)
4842 return true;
4843
4844 warnIfRegIndexIsAT(FirstReg, IDLoc);
4845
4846 assert(Inst.getOperand(2).isImm() &&
4847 "Offset for load macro is not immediate!");
4848
4849 MCOperand &FirstOffset = Inst.getOperand(2);
4850 signed NextOffset = FirstOffset.getImm() + 4;
4851 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4852
4853 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4854 return true;
4855
4856 // For loads, clobber the base register with the second load instead of the
4857 // first if the BaseReg == FirstReg.
4858 if (FirstReg != BaseReg || !IsLoad) {
4859 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4860 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4861 } else {
4862 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4863 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4864 }
4865
4866 return false;
4867}
4868
Simon Dardis43115a12016-11-21 20:30:41 +00004869bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4870 const MCSubtargetInfo *STI) {
4871
4872 warnIfNoMacro(IDLoc);
4873 MipsTargetStreamer &TOut = getTargetStreamer();
4874
4875 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4876 Inst.getOperand(2).getReg() != Mips::ZERO) {
4877 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4878 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4879 IDLoc, STI);
4880 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4881 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4882 return false;
4883 }
4884
4885 unsigned Reg = 0;
4886 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4887 Reg = Inst.getOperand(2).getReg();
4888 } else {
4889 Reg = Inst.getOperand(1).getReg();
4890 }
4891 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4892 return false;
4893}
4894
4895bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4896 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004897 warnIfNoMacro(IDLoc);
4898 MipsTargetStreamer &TOut = getTargetStreamer();
4899
4900 unsigned Opc;
4901 int64_t Imm = Inst.getOperand(2).getImm();
4902 unsigned Reg = Inst.getOperand(1).getReg();
4903
4904 if (Imm == 0) {
4905 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4906 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4907 return false;
4908 } else {
4909
4910 if (Reg == Mips::ZERO) {
4911 Warning(IDLoc, "comparison is always false");
4912 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4913 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4914 return false;
4915 }
4916
4917 if (Imm > -0x8000 && Imm < 0) {
4918 Imm = -Imm;
4919 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4920 } else {
4921 Opc = Mips::XORi;
4922 }
4923 }
4924 if (!isUInt<16>(Imm)) {
4925 unsigned ATReg = getATReg(IDLoc);
4926 if (!ATReg)
4927 return true;
4928
4929 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4930 Out, STI))
4931 return true;
4932
4933 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4934 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4935 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4936 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4937 return false;
4938 }
4939
4940 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4941 Imm, IDLoc, STI);
4942 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4943 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4944 return false;
4945}
4946
Simon Dardisde5ed0c2017-11-14 22:26:42 +00004947// Map the DSP accumulator and control register to the corresponding gpr
4948// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
4949// do not map the DSP registers contigously to gpr registers.
4950static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
4951 switch (Inst.getOpcode()) {
4952 case Mips::MFTLO:
4953 case Mips::MTTLO:
4954 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4955 case Mips::AC0:
4956 return Mips::ZERO;
4957 case Mips::AC1:
4958 return Mips::A0;
4959 case Mips::AC2:
4960 return Mips::T0;
4961 case Mips::AC3:
4962 return Mips::T4;
4963 default:
4964 llvm_unreachable("Unknown register for 'mttr' alias!");
4965 }
4966 case Mips::MFTHI:
4967 case Mips::MTTHI:
4968 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4969 case Mips::AC0:
4970 return Mips::AT;
4971 case Mips::AC1:
4972 return Mips::A1;
4973 case Mips::AC2:
4974 return Mips::T1;
4975 case Mips::AC3:
4976 return Mips::T5;
4977 default:
4978 llvm_unreachable("Unknown register for 'mttr' alias!");
4979 }
4980 case Mips::MFTACX:
4981 case Mips::MTTACX:
4982 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4983 case Mips::AC0:
4984 return Mips::V0;
4985 case Mips::AC1:
4986 return Mips::A2;
4987 case Mips::AC2:
4988 return Mips::T2;
4989 case Mips::AC3:
4990 return Mips::T6;
4991 default:
4992 llvm_unreachable("Unknown register for 'mttr' alias!");
4993 }
4994 case Mips::MFTDSP:
4995 case Mips::MTTDSP:
4996 return Mips::S0;
4997 default:
4998 llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
4999 }
5000}
5001
5002// Map the floating point register operand to the corresponding register
5003// operand.
5004static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
5005 switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
5006 case Mips::F0: return Mips::ZERO;
5007 case Mips::F1: return Mips::AT;
5008 case Mips::F2: return Mips::V0;
5009 case Mips::F3: return Mips::V1;
5010 case Mips::F4: return Mips::A0;
5011 case Mips::F5: return Mips::A1;
5012 case Mips::F6: return Mips::A2;
5013 case Mips::F7: return Mips::A3;
5014 case Mips::F8: return Mips::T0;
5015 case Mips::F9: return Mips::T1;
5016 case Mips::F10: return Mips::T2;
5017 case Mips::F11: return Mips::T3;
5018 case Mips::F12: return Mips::T4;
5019 case Mips::F13: return Mips::T5;
5020 case Mips::F14: return Mips::T6;
5021 case Mips::F15: return Mips::T7;
5022 case Mips::F16: return Mips::S0;
5023 case Mips::F17: return Mips::S1;
5024 case Mips::F18: return Mips::S2;
5025 case Mips::F19: return Mips::S3;
5026 case Mips::F20: return Mips::S4;
5027 case Mips::F21: return Mips::S5;
5028 case Mips::F22: return Mips::S6;
5029 case Mips::F23: return Mips::S7;
5030 case Mips::F24: return Mips::T8;
5031 case Mips::F25: return Mips::T9;
5032 case Mips::F26: return Mips::K0;
5033 case Mips::F27: return Mips::K1;
5034 case Mips::F28: return Mips::GP;
5035 case Mips::F29: return Mips::SP;
5036 case Mips::F30: return Mips::FP;
5037 case Mips::F31: return Mips::RA;
5038 default: llvm_unreachable("Unknown register for mttc1 alias!");
5039 }
5040}
5041
5042// Map the coprocessor operand the corresponding gpr register operand.
5043static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
5044 switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
5045 case Mips::COP00: return Mips::ZERO;
5046 case Mips::COP01: return Mips::AT;
5047 case Mips::COP02: return Mips::V0;
5048 case Mips::COP03: return Mips::V1;
5049 case Mips::COP04: return Mips::A0;
5050 case Mips::COP05: return Mips::A1;
5051 case Mips::COP06: return Mips::A2;
5052 case Mips::COP07: return Mips::A3;
5053 case Mips::COP08: return Mips::T0;
5054 case Mips::COP09: return Mips::T1;
5055 case Mips::COP010: return Mips::T2;
5056 case Mips::COP011: return Mips::T3;
5057 case Mips::COP012: return Mips::T4;
5058 case Mips::COP013: return Mips::T5;
5059 case Mips::COP014: return Mips::T6;
5060 case Mips::COP015: return Mips::T7;
5061 case Mips::COP016: return Mips::S0;
5062 case Mips::COP017: return Mips::S1;
5063 case Mips::COP018: return Mips::S2;
5064 case Mips::COP019: return Mips::S3;
5065 case Mips::COP020: return Mips::S4;
5066 case Mips::COP021: return Mips::S5;
5067 case Mips::COP022: return Mips::S6;
5068 case Mips::COP023: return Mips::S7;
5069 case Mips::COP024: return Mips::T8;
5070 case Mips::COP025: return Mips::T9;
5071 case Mips::COP026: return Mips::K0;
5072 case Mips::COP027: return Mips::K1;
5073 case Mips::COP028: return Mips::GP;
5074 case Mips::COP029: return Mips::SP;
5075 case Mips::COP030: return Mips::FP;
5076 case Mips::COP031: return Mips::RA;
5077 default: llvm_unreachable("Unknown register for mttc0 alias!");
5078 }
5079}
5080
5081/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
5082/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
5083bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5084 const MCSubtargetInfo *STI) {
5085 MipsTargetStreamer &TOut = getTargetStreamer();
5086 unsigned rd = 0;
5087 unsigned u = 1;
5088 unsigned sel = 0;
5089 unsigned h = 0;
5090 bool IsMFTR = false;
5091 switch (Inst.getOpcode()) {
5092 case Mips::MFTC0:
5093 IsMFTR = true;
5094 LLVM_FALLTHROUGH;
5095 case Mips::MTTC0:
5096 u = 0;
5097 rd = getRegisterForMxtrC0(Inst, IsMFTR);
5098 sel = Inst.getOperand(2).getImm();
5099 break;
5100 case Mips::MFTGPR:
5101 IsMFTR = true;
5102 LLVM_FALLTHROUGH;
5103 case Mips::MTTGPR:
5104 rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
5105 break;
5106 case Mips::MFTLO:
5107 case Mips::MFTHI:
5108 case Mips::MFTACX:
5109 case Mips::MFTDSP:
5110 IsMFTR = true;
5111 LLVM_FALLTHROUGH;
5112 case Mips::MTTLO:
5113 case Mips::MTTHI:
5114 case Mips::MTTACX:
5115 case Mips::MTTDSP:
5116 rd = getRegisterForMxtrDSP(Inst, IsMFTR);
5117 sel = 1;
5118 break;
5119 case Mips::MFTHC1:
5120 h = 1;
5121 LLVM_FALLTHROUGH;
5122 case Mips::MFTC1:
5123 IsMFTR = true;
5124 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5125 sel = 2;
5126 break;
5127 case Mips::MTTHC1:
5128 h = 1;
5129 LLVM_FALLTHROUGH;
5130 case Mips::MTTC1:
5131 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5132 sel = 2;
5133 break;
5134 case Mips::CFTC1:
5135 IsMFTR = true;
5136 LLVM_FALLTHROUGH;
5137 case Mips::CTTC1:
5138 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5139 sel = 3;
5140 break;
5141 }
5142 unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
5143 unsigned Op1 =
5144 IsMFTR ? rd
5145 : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
5146 : Inst.getOperand(0).getReg());
5147
5148 TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
5149 STI);
5150 return false;
5151}
5152
Daniel Sandersc5537422016-07-27 13:49:44 +00005153unsigned
5154MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
5155 const OperandVector &Operands) {
5156 switch (Inst.getOpcode()) {
5157 default:
5158 return Match_Success;
5159 case Mips::DATI:
5160 case Mips::DAHI:
Daniel Sandersb23005e2016-07-28 15:59:06 +00005161 if (static_cast<MipsOperand &>(*Operands[1])
5162 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
5163 return Match_Success;
5164 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00005165 }
5166}
Simon Dardis730fdb72017-01-16 13:55:58 +00005167
Matheus Almeida595fcab2014-06-11 15:05:56 +00005168unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00005169 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00005170 // As described by the MIPSR6 spec, daui must not use the zero operand for
5171 // its source operand.
5172 case Mips::DAUI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00005173 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5174 Inst.getOperand(1).getReg() == Mips::ZERO_64)
5175 return Match_RequiresNoZeroRegister;
5176 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00005177 // As described by the Mips32r2 spec, the registers Rd and Rs for
5178 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00005179 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00005180 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00005181 case Mips::JALR_HB:
Simon Dardis7bc8ad52018-02-21 00:06:53 +00005182 case Mips::JALR_HB64:
Simon Dardisb60833c2016-05-31 17:34:42 +00005183 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00005184 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00005185 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5186 return Match_RequiresDifferentSrcAndDst;
5187 return Match_Success;
5188 case Mips::LWP_MM:
Simon Dardisb60833c2016-05-31 17:34:42 +00005189 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
5190 return Match_RequiresDifferentSrcAndDst;
5191 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00005192 case Mips::SYNC:
5193 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
5194 return Match_NonZeroOperandForSync;
5195 return Match_Success;
Simon Dardis52ae4f02018-03-07 11:39:48 +00005196 case Mips::MFC0:
5197 case Mips::MTC0:
5198 case Mips::MTC2:
5199 case Mips::MFC2:
5200 if (Inst.getOperand(2).getImm() != 0 && !hasMips32())
5201 return Match_NonZeroOperandForMTCX;
5202 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005203 // As described the MIPSR6 spec, the compact branches that compare registers
5204 // must:
5205 // a) Not use the zero register.
5206 // b) Not use the same register twice.
5207 // c) rs < rt for bnec, beqc.
5208 // NB: For this case, the encoding will swap the operands as their
5209 // ordering doesn't matter. GAS performs this transformation too.
5210 // Hence, that constraint does not have to be enforced.
5211 //
5212 // The compact branches that branch iff the signed addition of two registers
5213 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
5214 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005215 case Mips::BLEZC: case Mips::BLEZC_MMR6:
5216 case Mips::BGEZC: case Mips::BGEZC_MMR6:
5217 case Mips::BGTZC: case Mips::BGTZC_MMR6:
5218 case Mips::BLTZC: case Mips::BLTZC_MMR6:
5219 case Mips::BEQZC: case Mips::BEQZC_MMR6:
5220 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005221 case Mips::BLEZC64:
5222 case Mips::BGEZC64:
5223 case Mips::BGTZC64:
5224 case Mips::BLTZC64:
5225 case Mips::BEQZC64:
5226 case Mips::BNEZC64:
5227 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5228 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005229 return Match_RequiresNoZeroRegister;
5230 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005231 case Mips::BGEC: case Mips::BGEC_MMR6:
5232 case Mips::BLTC: case Mips::BLTC_MMR6:
5233 case Mips::BGEUC: case Mips::BGEUC_MMR6:
5234 case Mips::BLTUC: case Mips::BLTUC_MMR6:
5235 case Mips::BEQC: case Mips::BEQC_MMR6:
5236 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005237 case Mips::BGEC64:
5238 case Mips::BLTC64:
5239 case Mips::BGEUC64:
5240 case Mips::BLTUC64:
5241 case Mips::BEQC64:
5242 case Mips::BNEC64:
5243 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5244 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005245 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00005246 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5247 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005248 return Match_RequiresNoZeroRegister;
5249 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5250 return Match_RequiresDifferentOperands;
5251 return Match_Success;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005252 case Mips::DINS: {
Simon Dardis55e44672017-09-14 17:27:53 +00005253 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5254 "Operands must be immediates for dins!");
5255 const signed Pos = Inst.getOperand(2).getImm();
5256 const signed Size = Inst.getOperand(3).getImm();
5257 if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
5258 return Match_RequiresPosSizeRange0_32;
5259 return Match_Success;
5260 }
5261 case Mips::DINSM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005262 case Mips::DINSU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005263 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5264 "Operands must be immediates for dinsm/dinsu!");
5265 const signed Pos = Inst.getOperand(2).getImm();
5266 const signed Size = Inst.getOperand(3).getImm();
5267 if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
5268 return Match_RequiresPosSizeRange33_64;
5269 return Match_Success;
5270 }
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005271 case Mips::DEXT: {
Simon Dardis55e44672017-09-14 17:27:53 +00005272 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5273 "Operands must be immediates for DEXTM!");
5274 const signed Pos = Inst.getOperand(2).getImm();
5275 const signed Size = Inst.getOperand(3).getImm();
5276 if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
5277 return Match_RequiresPosSizeUImm6;
5278 return Match_Success;
5279 }
5280 case Mips::DEXTM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005281 case Mips::DEXTU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005282 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5283 "Operands must be immediates for dextm/dextu!");
5284 const signed Pos = Inst.getOperand(2).getImm();
5285 const signed Size = Inst.getOperand(3).getImm();
5286 if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
5287 return Match_RequiresPosSizeRange33_64;
5288 return Match_Success;
5289 }
Petar Jovanovic3408caf2018-03-14 14:13:31 +00005290 case Mips::CRC32B: case Mips::CRC32CB:
5291 case Mips::CRC32H: case Mips::CRC32CH:
5292 case Mips::CRC32W: case Mips::CRC32CW:
5293 case Mips::CRC32D: case Mips::CRC32CD:
5294 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())
5295 return Match_RequiresSameSrcAndDst;
5296 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005297 }
Simon Dardis730fdb72017-01-16 13:55:58 +00005298
5299 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
5300 if ((TSFlags & MipsII::HasFCCRegOperand) &&
5301 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
5302 return Match_NoFCCRegisterForCurrentISA;
5303
5304 return Match_Success;
5305
Matheus Almeida595fcab2014-06-11 15:05:56 +00005306}
5307
Daniel Sanders52da7af2015-11-06 12:11:03 +00005308static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
5309 uint64_t ErrorInfo) {
5310 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
5311 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
5312 if (ErrorLoc == SMLoc())
5313 return Loc;
5314 return ErrorLoc;
5315 }
5316 return Loc;
5317}
5318
David Blaikie960ea3f2014-06-08 16:18:35 +00005319bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5320 OperandVector &Operands,
5321 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005322 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005323 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005324 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005325 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005326 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005327
5328 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005329 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005330 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005331 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005332 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005333 case Match_MissingFeature:
5334 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5335 return true;
5336 case Match_InvalidOperand: {
5337 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005338 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005339 if (ErrorInfo >= Operands.size())
5340 return Error(IDLoc, "too few operands for instruction");
5341
Daniel Sanders52da7af2015-11-06 12:11:03 +00005342 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005343 if (ErrorLoc == SMLoc())
5344 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005345 }
5346
5347 return Error(ErrorLoc, "invalid operand for instruction");
5348 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005349 case Match_NonZeroOperandForSync:
Simon Atanasyan478220f2018-05-24 07:36:00 +00005350 return Error(IDLoc,
5351 "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Simon Dardis52ae4f02018-03-07 11:39:48 +00005352 case Match_NonZeroOperandForMTCX:
5353 return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005354 case Match_MnemonicFail:
5355 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005356 case Match_RequiresDifferentSrcAndDst:
5357 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005358 case Match_RequiresDifferentOperands:
5359 return Error(IDLoc, "registers must be different");
5360 case Match_RequiresNoZeroRegister:
5361 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005362 case Match_RequiresSameSrcAndDst:
5363 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005364 case Match_NoFCCRegisterForCurrentISA:
5365 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5366 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005367 case Match_Immz:
5368 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005369 case Match_UImm1_0:
5370 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5371 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005372 case Match_UImm2_0:
5373 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5374 "expected 2-bit unsigned immediate");
5375 case Match_UImm2_1:
5376 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5377 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005378 case Match_UImm3_0:
5379 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5380 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005381 case Match_UImm4_0:
5382 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5383 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005384 case Match_SImm4_0:
5385 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5386 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005387 case Match_UImm5_0:
5388 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5389 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005390 case Match_SImm5_0:
5391 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5392 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005393 case Match_UImm5_1:
5394 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5395 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005396 case Match_UImm5_32:
5397 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5398 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005399 case Match_UImm5_33:
5400 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5401 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005402 case Match_UImm5_0_Report_UImm6:
5403 // This is used on UImm5 operands that have a corresponding UImm5_32
5404 // operand to avoid confusing the user.
5405 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5406 "expected 6-bit unsigned immediate");
5407 case Match_UImm5_Lsl2:
5408 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5409 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005410 case Match_UImmRange2_64:
5411 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5412 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005413 case Match_UImm6_0:
5414 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5415 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005416 case Match_UImm6_Lsl2:
5417 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5418 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005419 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005420 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5421 "expected 6-bit signed immediate");
5422 case Match_UImm7_0:
5423 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5424 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005425 case Match_UImm7_N1:
5426 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5427 "expected immediate in range -1 .. 126");
5428 case Match_SImm7_Lsl2:
5429 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5430 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005431 case Match_UImm8_0:
5432 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5433 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005434 case Match_UImm10_0:
5435 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5436 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005437 case Match_SImm10_0:
5438 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5439 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005440 case Match_SImm11_0:
5441 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5442 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005443 case Match_UImm16:
5444 case Match_UImm16_Relaxed:
Petar Jovanovice4dacb72017-09-12 21:43:33 +00005445 case Match_UImm16_AltRelaxed:
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005446 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5447 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005448 case Match_SImm16:
5449 case Match_SImm16_Relaxed:
5450 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5451 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005452 case Match_SImm19_Lsl2:
5453 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5454 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005455 case Match_UImm20_0:
5456 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5457 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005458 case Match_UImm26_0:
5459 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5460 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005461 case Match_SImm32:
5462 case Match_SImm32_Relaxed:
5463 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5464 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005465 case Match_UImm32_Coerced:
5466 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5467 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005468 case Match_MemSImm9:
5469 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5470 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005471 case Match_MemSImm10:
5472 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5473 "expected memory with 10-bit signed offset");
5474 case Match_MemSImm10Lsl1:
5475 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5476 "expected memory with 11-bit signed offset and multiple of 2");
5477 case Match_MemSImm10Lsl2:
5478 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5479 "expected memory with 12-bit signed offset and multiple of 4");
5480 case Match_MemSImm10Lsl3:
5481 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5482 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005483 case Match_MemSImm11:
5484 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5485 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005486 case Match_MemSImm12:
5487 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5488 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005489 case Match_MemSImm16:
5490 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5491 "expected memory with 16-bit signed offset");
Simon Atanasyand4d892f2018-04-26 19:55:28 +00005492 case Match_MemSImmPtr:
5493 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5494 "expected memory with 32-bit signed offset");
Simon Dardis6f83ae32017-09-14 15:17:50 +00005495 case Match_RequiresPosSizeRange0_32: {
5496 SMLoc ErrorStart = Operands[3]->getStartLoc();
5497 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5498 return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
5499 SMRange(ErrorStart, ErrorEnd));
5500 }
Simon Dardis55e44672017-09-14 17:27:53 +00005501 case Match_RequiresPosSizeUImm6: {
5502 SMLoc ErrorStart = Operands[3]->getStartLoc();
5503 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5504 return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
5505 SMRange(ErrorStart, ErrorEnd));
5506 }
Simon Dardis6f83ae32017-09-14 15:17:50 +00005507 case Match_RequiresPosSizeRange33_64: {
5508 SMLoc ErrorStart = Operands[3]->getStartLoc();
5509 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5510 return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
5511 SMRange(ErrorStart, ErrorEnd));
5512 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005513 }
Craig Topper589ceee2015-01-03 08:16:34 +00005514
5515 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005516}
5517
Toma Tabacud9d344b2015-04-27 14:05:04 +00005518void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5519 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5520 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5521 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005522}
5523
Toma Tabacu81496c12015-05-20 08:54:45 +00005524void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5525 if (!AssemblerOptions.back()->isMacro())
5526 Warning(Loc, "macro instruction expanded into multiple instructions");
5527}
5528
Simon Dardis6a319922018-05-25 16:15:48 +00005529void MipsAsmParser::ConvertXWPOperands(MCInst &Inst,
5530 const OperandVector &Operands) {
5531 assert(
5532 (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) &&
5533 "Unexpected instruction!");
5534 ((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, 1);
5535 int NextReg = nextReg(((MipsOperand &)*Operands[1]).getGPR32Reg());
5536 Inst.addOperand(MCOperand::createReg(NextReg));
5537 ((MipsOperand &)*Operands[2]).addMemOperands(Inst, 2);
5538}
5539
Daniel Sandersef638fe2014-10-03 15:37:37 +00005540void
5541MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5542 SMRange Range, bool ShowColors) {
5543 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005544 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005545 ShowColors);
5546}
5547
Jack Carter1ac53222013-02-20 23:11:17 +00005548int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005549 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005550
Vladimir Medic4c299852013-11-06 11:27:05 +00005551 CC = StringSwitch<unsigned>(Name)
5552 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005553 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005554 .Case("a0", 4)
5555 .Case("a1", 5)
5556 .Case("a2", 6)
5557 .Case("a3", 7)
5558 .Case("v0", 2)
5559 .Case("v1", 3)
5560 .Case("s0", 16)
5561 .Case("s1", 17)
5562 .Case("s2", 18)
5563 .Case("s3", 19)
5564 .Case("s4", 20)
5565 .Case("s5", 21)
5566 .Case("s6", 22)
5567 .Case("s7", 23)
5568 .Case("k0", 26)
5569 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005570 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005571 .Case("sp", 29)
5572 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005573 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005574 .Case("ra", 31)
5575 .Case("t0", 8)
5576 .Case("t1", 9)
5577 .Case("t2", 10)
5578 .Case("t3", 11)
5579 .Case("t4", 12)
5580 .Case("t5", 13)
5581 .Case("t6", 14)
5582 .Case("t7", 15)
5583 .Case("t8", 24)
5584 .Case("t9", 25)
5585 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005586
Toma Tabacufda445c2014-09-15 15:33:01 +00005587 if (!(isABI_N32() || isABI_N64()))
5588 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005589
Daniel Sandersef638fe2014-10-03 15:37:37 +00005590 if (12 <= CC && CC <= 15) {
5591 // Name is one of t4-t7
5592 AsmToken RegTok = getLexer().peekTok();
5593 SMRange RegRange = RegTok.getLocRange();
5594
5595 StringRef FixedName = StringSwitch<StringRef>(Name)
5596 .Case("t4", "t0")
5597 .Case("t5", "t1")
5598 .Case("t6", "t2")
5599 .Case("t7", "t3")
5600 .Default("");
5601 assert(FixedName != "" && "Register name is not one of t4-t7.");
5602
5603 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5604 "Did you mean $" + FixedName + "?", RegRange);
5605 }
5606
Toma Tabacufda445c2014-09-15 15:33:01 +00005607 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5608 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5609 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5610 if (8 <= CC && CC <= 11)
5611 CC += 4;
5612
5613 if (CC == -1)
5614 CC = StringSwitch<unsigned>(Name)
5615 .Case("a4", 8)
5616 .Case("a5", 9)
5617 .Case("a6", 10)
5618 .Case("a7", 11)
5619 .Case("kt0", 26)
5620 .Case("kt1", 27)
5621 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005622
5623 return CC;
5624}
Jack Carterd0bd6422013-04-18 00:41:53 +00005625
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005626int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5627 int CC;
5628
5629 CC = StringSwitch<unsigned>(Name)
5630 .Case("hwr_cpunum", 0)
5631 .Case("hwr_synci_step", 1)
5632 .Case("hwr_cc", 2)
5633 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005634 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005635 .Default(-1);
5636
5637 return CC;
5638}
5639
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005640int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005641 if (Name[0] == 'f') {
5642 StringRef NumString = Name.substr(1);
5643 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005644 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005645 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005646 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005647 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005648 return IntVal;
5649 }
5650 return -1;
5651}
Jack Cartera63b16a2012-09-07 00:23:42 +00005652
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005653int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005654 if (Name.startswith("fcc")) {
5655 StringRef NumString = Name.substr(3);
5656 unsigned IntVal;
5657 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005658 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005659 if (IntVal > 7) // There are only 8 fcc registers.
5660 return -1;
5661 return IntVal;
5662 }
5663 return -1;
5664}
5665
5666int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005667 if (Name.startswith("ac")) {
5668 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005669 unsigned IntVal;
5670 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005671 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005672 if (IntVal > 3) // There are only 3 acc registers.
5673 return -1;
5674 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005675 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005676 return -1;
5677}
Jack Carterd0bd6422013-04-18 00:41:53 +00005678
Jack Carter5dc8ac92013-09-25 23:50:44 +00005679int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5680 unsigned IntVal;
5681
5682 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5683 return -1;
5684
5685 if (IntVal > 31)
5686 return -1;
5687
5688 return IntVal;
5689}
5690
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005691int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5692 int CC;
5693
5694 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005695 .Case("msair", 0)
5696 .Case("msacsr", 1)
5697 .Case("msaaccess", 2)
5698 .Case("msasave", 3)
5699 .Case("msamodify", 4)
5700 .Case("msarequest", 5)
5701 .Case("msamap", 6)
5702 .Case("msaunmap", 7)
5703 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005704
5705 return CC;
5706}
5707
Simon Dardis3aa8a902017-02-06 12:43:46 +00005708bool MipsAsmParser::canUseATReg() {
5709 return AssemblerOptions.back()->getATRegIndex() != 0;
5710}
5711
Toma Tabacu89a712b2015-04-15 10:48:56 +00005712unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005713 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005714 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005715 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005716 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005717 return 0;
5718 }
5719 unsigned AT = getReg(
5720 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005721 return AT;
5722}
Jack Carter0b744b32012-10-04 02:29:46 +00005723
Jack Carterd0bd6422013-04-18 00:41:53 +00005724unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005725 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005726}
5727
Toma Tabacu13964452014-09-04 13:23:44 +00005728bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005729 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005730 LLVM_DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005731
Jack Carter30a59822012-10-04 04:03:53 +00005732 // Check if the current operand has a custom associated parser, if so, try to
5733 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005734 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5735 if (ResTy == MatchOperand_Success)
5736 return false;
5737 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5738 // there was a match, but an error occurred, in which case, just return that
5739 // the operand parsing failed.
5740 if (ResTy == MatchOperand_ParseFail)
5741 return true;
5742
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005743 LLVM_DEBUG(dbgs() << ".. Generic Parser\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005744
Jack Carterb4dbc172012-09-05 23:34:03 +00005745 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005746 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005747 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005748 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005749
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005750 // Almost all registers have been parsed by custom parsers. There is only
5751 // one exception to this. $zero (and it's alias $0) will reach this point
5752 // for div, divu, and similar instructions because it is not an operand
5753 // to the instruction definition but an explicit register. Special case
5754 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005755 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005756 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005757
Jack Carterd0bd6422013-04-18 00:41:53 +00005758 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005759 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005760 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005761 return true;
5762
Jack Carter873c7242013-01-12 01:03:14 +00005763 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005764 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005765 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005766 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005767 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005768
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005769 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005770 return false;
5771 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005772 default: {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005773 LLVM_DEBUG(dbgs() << ".. generic integer expression\n");
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005774
5775 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005776 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005777 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005778 return true;
5779
Jack Carter873c7242013-01-12 01:03:14 +00005780 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5781
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005782 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005783 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005784 }
Jack Carter0b744b32012-10-04 02:29:46 +00005785 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005786 return true;
5787}
5788
Jack Carterb5cf5902013-04-17 00:18:04 +00005789bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005790 switch (Expr->getKind()) {
5791 case MCExpr::Constant:
5792 return true;
5793 case MCExpr::SymbolRef:
5794 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
Simon Dardisc6be2252017-08-09 10:47:52 +00005795 case MCExpr::Binary: {
Simon Dardis02c9a3d2017-08-18 13:27:02 +00005796 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
Simon Dardisc6be2252017-08-09 10:47:52 +00005797 if (!isEvaluated(BE->getLHS()))
5798 return false;
5799 return isEvaluated(BE->getRHS());
5800 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005801 case MCExpr::Unary:
5802 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005803 case MCExpr::Target:
5804 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005805 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005806 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005807}
Jack Carterd0bd6422013-04-18 00:41:53 +00005808
Jack Carterb4dbc172012-09-05 23:34:03 +00005809bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5810 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005811 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005812 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005813 if (ResTy == MatchOperand_Success) {
5814 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005815 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005816 StartLoc = Operand.getStartLoc();
5817 EndLoc = Operand.getEndLoc();
5818
5819 // AFAIK, we only support numeric registers and named GPR's in CFI
5820 // directives.
5821 // Don't worry about eating tokens before failing. Using an unrecognised
5822 // register is a parse error.
5823 if (Operand.isGPRAsmReg()) {
5824 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005825 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005826 }
5827
5828 return (RegNo == (unsigned)-1);
5829 }
5830
5831 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005832 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005833}
5834
Jack Carterb5cf5902013-04-17 00:18:04 +00005835bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005836 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005837
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005838 if (isParenExpr)
5839 return getParser().parseParenExprOfDepth(0, Res, S);
5840 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005841}
5842
Alex Bradbury58eba092016-11-01 16:32:05 +00005843OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005844MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005845 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005846 LLVM_DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005847 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005848 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005849 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005850 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005851 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005852 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005853
Jack Carterb5cf5902013-04-17 00:18:04 +00005854 if (getLexer().getKind() == AsmToken::LParen) {
5855 Parser.Lex();
5856 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005857 }
5858
Jack Carterb5cf5902013-04-17 00:18:04 +00005859 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005860 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005861 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005862
Jack Carterd0bd6422013-04-18 00:41:53 +00005863 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005864 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005865 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005866 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005867 SMLoc E =
5868 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005869 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005870 return MatchOperand_Success;
5871 }
5872 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005873 SMLoc E =
5874 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005875
Jack Carterd0bd6422013-04-18 00:41:53 +00005876 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005877 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005878 auto Base = MipsOperand::createGPRReg(
5879 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005880 Operands.push_back(
5881 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005882 return MatchOperand_Success;
5883 }
Simon Dardis858915f2016-10-18 15:17:17 +00005884 MCBinaryExpr::Opcode Opcode;
5885 // GAS and LLVM treat comparison operators different. GAS will generate -1
5886 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5887 // highly unlikely to be found in a memory offset expression, we don't
5888 // handle them.
5889 switch (Tok.getKind()) {
5890 case AsmToken::Plus:
5891 Opcode = MCBinaryExpr::Add;
5892 Parser.Lex();
5893 break;
5894 case AsmToken::Minus:
5895 Opcode = MCBinaryExpr::Sub;
5896 Parser.Lex();
5897 break;
5898 case AsmToken::Star:
5899 Opcode = MCBinaryExpr::Mul;
5900 Parser.Lex();
5901 break;
5902 case AsmToken::Pipe:
5903 Opcode = MCBinaryExpr::Or;
5904 Parser.Lex();
5905 break;
5906 case AsmToken::Amp:
5907 Opcode = MCBinaryExpr::And;
5908 Parser.Lex();
5909 break;
5910 case AsmToken::LessLess:
5911 Opcode = MCBinaryExpr::Shl;
5912 Parser.Lex();
5913 break;
5914 case AsmToken::GreaterGreater:
5915 Opcode = MCBinaryExpr::LShr;
5916 Parser.Lex();
5917 break;
5918 case AsmToken::Caret:
5919 Opcode = MCBinaryExpr::Xor;
5920 Parser.Lex();
5921 break;
5922 case AsmToken::Slash:
5923 Opcode = MCBinaryExpr::Div;
5924 Parser.Lex();
5925 break;
5926 case AsmToken::Percent:
5927 Opcode = MCBinaryExpr::Mod;
5928 Parser.Lex();
5929 break;
5930 default:
5931 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5932 return MatchOperand_ParseFail;
5933 }
5934 const MCExpr * NextExpr;
5935 if (getParser().parseExpression(NextExpr))
5936 return MatchOperand_ParseFail;
5937 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005938 }
5939
Jack Carterd0bd6422013-04-18 00:41:53 +00005940 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005941 }
5942
Toma Tabacu13964452014-09-04 13:23:44 +00005943 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005944 if (Res != MatchOperand_Success)
5945 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005946
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005947 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005948 Error(Parser.getTok().getLoc(), "')' expected");
5949 return MatchOperand_ParseFail;
5950 }
5951
Jack Carter873c7242013-01-12 01:03:14 +00005952 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5953
Jack Carterd0bd6422013-04-18 00:41:53 +00005954 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005955
Craig Topper062a2ba2014-04-25 05:30:21 +00005956 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005957 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005958
Jack Carterd0bd6422013-04-18 00:41:53 +00005959 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005960 std::unique_ptr<MipsOperand> op(
5961 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005962 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005963 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005964 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005965 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005966 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5967 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005968 if (IdVal->evaluateAsAbsolute(Imm))
5969 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005970 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005971 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005972 getContext());
5973 }
5974
David Blaikie960ea3f2014-06-08 16:18:35 +00005975 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005976 return MatchOperand_Success;
5977}
5978
David Blaikie960ea3f2014-06-08 16:18:35 +00005979bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005980 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005981 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00005982 if (!Sym)
5983 return false;
5984
5985 SMLoc S = Parser.getTok().getLoc();
5986 if (Sym->isVariable()) {
5987 const MCExpr *Expr = Sym->getVariableValue();
Jack Carterd76b2372013-03-21 21:44:16 +00005988 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005989 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005990 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005991 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005992 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005993 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005994 if (ResTy == MatchOperand_Success) {
5995 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005996 return true;
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00005997 }
5998 if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005999 llvm_unreachable("Should never ParseFail");
Jack Carterd76b2372013-03-21 21:44:16 +00006000 }
Jack Carterd76b2372013-03-21 21:44:16 +00006001 }
Simon Atanasyan69301c92018-05-29 15:58:06 +00006002 } else if (Sym->isUnset()) {
6003 // If symbol is unset, it might be created in the `parseSetAssignment`
6004 // routine as an alias for a numeric register name.
6005 // Lookup in the aliases list.
6006 auto Entry = RegisterSets.find(Sym->getName());
6007 if (Entry != RegisterSets.end()) {
6008 OperandMatchResultTy ResTy =
6009 matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S);
6010 if (ResTy == MatchOperand_Success) {
6011 Parser.Lex();
6012 return true;
6013 }
6014 }
Jack Carterd76b2372013-03-21 21:44:16 +00006015 }
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00006016
Jack Carterd76b2372013-03-21 21:44:16 +00006017 return false;
6018}
Jack Carterd0bd6422013-04-18 00:41:53 +00006019
Alex Bradbury58eba092016-11-01 16:32:05 +00006020OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006021MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00006022 StringRef Identifier,
6023 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006024 int Index = matchCPURegisterName(Identifier);
6025 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006026 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006027 Index, Identifier, getContext().getRegisterInfo(), S,
6028 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006029 return MatchOperand_Success;
6030 }
6031
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00006032 Index = matchHWRegsRegisterName(Identifier);
6033 if (Index != -1) {
6034 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006035 Index, Identifier, getContext().getRegisterInfo(), S,
6036 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00006037 return MatchOperand_Success;
6038 }
6039
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006040 Index = matchFPURegisterName(Identifier);
6041 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006042 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006043 Index, Identifier, getContext().getRegisterInfo(), S,
6044 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006045 return MatchOperand_Success;
6046 }
6047
6048 Index = matchFCCRegisterName(Identifier);
6049 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006050 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006051 Index, Identifier, getContext().getRegisterInfo(), S,
6052 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006053 return MatchOperand_Success;
6054 }
6055
6056 Index = matchACRegisterName(Identifier);
6057 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006058 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006059 Index, Identifier, getContext().getRegisterInfo(), S,
6060 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006061 return MatchOperand_Success;
6062 }
6063
6064 Index = matchMSA128RegisterName(Identifier);
6065 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006066 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006067 Index, Identifier, getContext().getRegisterInfo(), S,
6068 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006069 return MatchOperand_Success;
6070 }
6071
6072 Index = matchMSA128CtrlRegisterName(Identifier);
6073 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006074 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006075 Index, Identifier, getContext().getRegisterInfo(), S,
6076 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006077 return MatchOperand_Success;
6078 }
6079
6080 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00006081}
6082
Alex Bradbury58eba092016-11-01 16:32:05 +00006083OperandMatchResultTy
Simon Atanasyan69301c92018-05-29 15:58:06 +00006084MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands,
6085 const AsmToken &Token, SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006086 if (Token.is(AsmToken::Identifier)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006087 LLVM_DEBUG(dbgs() << ".. identifier\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006088 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00006089 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00006090 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00006091 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006092 } else if (Token.is(AsmToken::Integer)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006093 LLVM_DEBUG(dbgs() << ".. integer\n");
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006094 int64_t RegNum = Token.getIntVal();
6095 if (RegNum < 0 || RegNum > 31) {
6096 // Show the error, but treat invalid register
6097 // number as a normal one to continue parsing
6098 // and catch other possible errors.
6099 Error(getLexer().getLoc(), "invalid register number");
6100 }
Toma Tabacu13964452014-09-04 13:23:44 +00006101 Operands.push_back(MipsOperand::createNumericReg(
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006102 RegNum, Token.getString(), getContext().getRegisterInfo(), S,
Daniel Sandersc5537422016-07-27 13:49:44 +00006103 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006104 return MatchOperand_Success;
6105 }
6106
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00006107 LLVM_DEBUG(dbgs() << Token.getKind() << "\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006108
6109 return MatchOperand_NoMatch;
6110}
6111
Alex Bradbury58eba092016-11-01 16:32:05 +00006112OperandMatchResultTy
Simon Atanasyan69301c92018-05-29 15:58:06 +00006113MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
6114 auto Token = getLexer().peekTok(false);
6115 return matchAnyRegisterWithoutDollar(Operands, Token, S);
6116}
6117
6118OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006119MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006120 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006121 LLVM_DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006122
6123 auto Token = Parser.getTok();
6124
6125 SMLoc S = Token.getLoc();
6126
6127 if (Token.isNot(AsmToken::Dollar)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006128 LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006129 if (Token.is(AsmToken::Identifier)) {
6130 if (searchSymbolAlias(Operands))
6131 return MatchOperand_Success;
6132 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006133 LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006134 return MatchOperand_NoMatch;
6135 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006136 LLVM_DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006137
Toma Tabacu13964452014-09-04 13:23:44 +00006138 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00006139 if (ResTy == MatchOperand_Success) {
6140 Parser.Lex(); // $
6141 Parser.Lex(); // identifier
6142 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006143 return ResTy;
6144}
6145
Alex Bradbury58eba092016-11-01 16:32:05 +00006146OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006147MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006148 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006149 LLVM_DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006150
6151 SMLoc S = getLexer().getLoc();
6152
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006153 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006154 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006155 if (ResTy != MatchOperand_NoMatch)
6156 return ResTy;
6157
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006158 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00006159 const MCExpr *Expr = nullptr;
6160 if (Parser.parseExpression(Expr)) {
6161 // We have no way of knowing if a symbol was consumed so we must ParseFail
6162 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006163 }
Daniel Sandersffd84362014-04-01 10:41:48 +00006164 Operands.push_back(
6165 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006166 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00006167}
6168
Alex Bradbury58eba092016-11-01 16:32:05 +00006169OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00006170MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006171 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00006172 const MCExpr *IdVal;
Simon Dardisa17a7b62017-10-10 13:34:45 +00006173 // If the first token is '$' we may have register operand. We have to reject
6174 // cases where it is not a register. Complicating the matter is that
6175 // register names are not reserved across all ABIs.
6176 // Peek past the dollar to see if it's a register name for this ABI.
Vladimir Medic2b953d02013-10-01 09:48:56 +00006177 SMLoc S = Parser.getTok().getLoc();
Simon Dardisa17a7b62017-10-10 13:34:45 +00006178 if (Parser.getTok().is(AsmToken::Dollar)) {
6179 return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
6180 ? MatchOperand_ParseFail
6181 : MatchOperand_NoMatch;
6182 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00006183 if (getParser().parseExpression(IdVal))
6184 return MatchOperand_ParseFail;
6185 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Simon Dardisa17a7b62017-10-10 13:34:45 +00006186 if (!MCE)
6187 return MatchOperand_NoMatch;
Vladimir Medic2b953d02013-10-01 09:48:56 +00006188 int64_t Val = MCE->getValue();
6189 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
6190 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00006191 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00006192 return MatchOperand_Success;
6193}
6194
Alex Bradbury58eba092016-11-01 16:32:05 +00006195OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006196MipsAsmParser::parseRegisterList(OperandVector &Operands) {
6197 MCAsmParser &Parser = getParser();
6198 SmallVector<unsigned, 10> Regs;
6199 unsigned RegNo;
6200 unsigned PrevReg = Mips::NoRegister;
6201 bool RegRange = false;
6202 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6203
6204 if (Parser.getTok().isNot(AsmToken::Dollar))
6205 return MatchOperand_ParseFail;
6206
6207 SMLoc S = Parser.getTok().getLoc();
6208 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
6209 SMLoc E = getLexer().getLoc();
6210 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
6211 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
6212 if (RegRange) {
6213 // Remove last register operand because registers from register range
6214 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006215 if ((isGP64bit() && RegNo == Mips::RA_64) ||
6216 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006217 Regs.push_back(RegNo);
6218 } else {
6219 unsigned TmpReg = PrevReg + 1;
6220 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006221 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
6222 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
6223 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006224 Error(E, "invalid register operand");
6225 return MatchOperand_ParseFail;
6226 }
6227
6228 PrevReg = TmpReg;
6229 Regs.push_back(TmpReg++);
6230 }
6231 }
6232
6233 RegRange = false;
6234 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006235 if ((PrevReg == Mips::NoRegister) &&
6236 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
6237 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006238 Error(E, "$16 or $31 expected");
6239 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006240 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
6241 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
6242 !isGP64bit()) ||
6243 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
6244 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
6245 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006246 Error(E, "invalid register operand");
6247 return MatchOperand_ParseFail;
6248 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006249 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
6250 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
6251 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006252 Error(E, "consecutive register numbers expected");
6253 return MatchOperand_ParseFail;
6254 }
6255
6256 Regs.push_back(RegNo);
6257 }
6258
6259 if (Parser.getTok().is(AsmToken::Minus))
6260 RegRange = true;
6261
6262 if (!Parser.getTok().isNot(AsmToken::Minus) &&
6263 !Parser.getTok().isNot(AsmToken::Comma)) {
6264 Error(E, "',' or '-' expected");
6265 return MatchOperand_ParseFail;
6266 }
6267
6268 Lex(); // Consume comma or minus
6269 if (Parser.getTok().isNot(AsmToken::Dollar))
6270 break;
6271
6272 PrevReg = RegNo;
6273 }
6274
6275 SMLoc E = Parser.getTok().getLoc();
6276 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6277 parseMemOperand(Operands);
6278 return MatchOperand_Success;
6279}
6280
Alex Bradbury58eba092016-11-01 16:32:05 +00006281OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00006282MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
6283 MCAsmParser &Parser = getParser();
6284 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6285 SmallVector<unsigned, 10> Regs;
6286
6287 if (Parser.getTok().isNot(AsmToken::Dollar))
6288 return MatchOperand_ParseFail;
6289
6290 SMLoc S = Parser.getTok().getLoc();
6291
6292 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6293 return MatchOperand_ParseFail;
6294
6295 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6296 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6297 Regs.push_back(RegNo);
6298
6299 SMLoc E = Parser.getTok().getLoc();
6300 if (Parser.getTok().isNot(AsmToken::Comma)) {
6301 Error(E, "',' expected");
6302 return MatchOperand_ParseFail;
6303 }
6304
6305 // Remove comma.
6306 Parser.Lex();
6307
6308 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6309 return MatchOperand_ParseFail;
6310
6311 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6312 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6313 Regs.push_back(RegNo);
6314
6315 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6316
6317 return MatchOperand_Success;
6318}
6319
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006320/// Sometimes (i.e. load/stores) the operand may be followed immediately by
6321/// either this.
6322/// ::= '(', register, ')'
6323/// handle it before we iterate so we don't get tripped up by the lack of
6324/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006325bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006326 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006327 if (getLexer().is(AsmToken::LParen)) {
6328 Operands.push_back(
6329 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
6330 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006331 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006332 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006333 return Error(Loc, "unexpected token in argument list");
6334 }
6335 if (Parser.getTok().isNot(AsmToken::RParen)) {
6336 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006337 return Error(Loc, "unexpected token, expected ')'");
6338 }
6339 Operands.push_back(
6340 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
6341 Parser.Lex();
6342 }
6343 return false;
6344}
6345
6346/// Sometimes (i.e. in MSA) the operand may be followed immediately by
6347/// either one of these.
6348/// ::= '[', register, ']'
6349/// ::= '[', integer, ']'
6350/// handle it before we iterate so we don't get tripped up by the lack of
6351/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006352bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00006353 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006354 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006355 if (getLexer().is(AsmToken::LBrac)) {
6356 Operands.push_back(
6357 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
6358 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006359 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006360 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006361 return Error(Loc, "unexpected token in argument list");
6362 }
6363 if (Parser.getTok().isNot(AsmToken::RBrac)) {
6364 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006365 return Error(Loc, "unexpected token, expected ']'");
6366 }
6367 Operands.push_back(
6368 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
6369 Parser.Lex();
6370 }
6371 return false;
6372}
6373
Simon Atanasyanc49da2e2018-09-13 08:38:03 +00006374static std::string MipsMnemonicSpellCheck(StringRef S, uint64_t FBS,
6375 unsigned VariantID = 0);
6376
David Blaikie960ea3f2014-06-08 16:18:35 +00006377bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6378 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006379 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006380 LLVM_DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006381
6382 // We have reached first instruction, module directive are now forbidden.
6383 getTargetStreamer().forbidModuleDirective();
6384
Vladimir Medic74593e62013-07-17 15:00:42 +00006385 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006386 if (!mnemonicIsValid(Name, 0)) {
Simon Atanasyanc49da2e2018-09-13 08:38:03 +00006387 uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
6388 std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS);
6389 return Error(NameLoc, "unknown instruction" + Suggestion);
Vladimir Medic74593e62013-07-17 15:00:42 +00006390 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006391 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006392 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006393
6394 // Read the remaining operands.
6395 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6396 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006397 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006398 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006399 return Error(Loc, "unexpected token in argument list");
6400 }
Toma Tabacu13964452014-09-04 13:23:44 +00006401 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006402 return true;
6403 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006404
Jack Carterd0bd6422013-04-18 00:41:53 +00006405 while (getLexer().is(AsmToken::Comma)) {
6406 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006407 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006408 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006409 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006410 return Error(Loc, "unexpected token in argument list");
6411 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006412 // Parse bracket and parenthesis suffixes before we iterate
6413 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006414 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006415 return true;
6416 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006417 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006418 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006419 }
6420 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006421 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6422 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006423 return Error(Loc, "unexpected token in argument list");
6424 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006425 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006426 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006427}
6428
Nirav Dave996fc132016-05-05 14:15:46 +00006429// FIXME: Given that these have the same name, these should both be
6430// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006431bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006432 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006433 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006434}
6435
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006436bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006437 return Error(Loc, ErrorMsg);
6438}
6439
Jack Carter0b744b32012-10-04 02:29:46 +00006440bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006441 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006442 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006443
6444 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006445 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006446
6447 Parser.Lex(); // Eat "noat".
6448
Jack Carterd0bd6422013-04-18 00:41:53 +00006449 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006450 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006451 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006452 return false;
6453 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006454
6455 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006456 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006457 return false;
6458}
Jack Carterd0bd6422013-04-18 00:41:53 +00006459
Jack Carter0b744b32012-10-04 02:29:46 +00006460bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006461 // Line can be: ".set at", which sets $at to $1
6462 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006463 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006464 Parser.Lex(); // Eat "at".
6465
Jack Carter0b744b32012-10-04 02:29:46 +00006466 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006467 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006468 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006469
6470 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006471 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006472 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006473 }
6474
6475 if (getLexer().isNot(AsmToken::Equal)) {
6476 reportParseError("unexpected token, expected equals sign");
6477 return false;
6478 }
6479 Parser.Lex(); // Eat "=".
6480
6481 if (getLexer().isNot(AsmToken::Dollar)) {
6482 if (getLexer().is(AsmToken::EndOfStatement)) {
6483 reportParseError("no register specified");
6484 return false;
6485 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006486 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006487 return false;
6488 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006489 }
6490 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006491
Toma Tabacu16a74492015-02-13 10:30:57 +00006492 // Find out what "reg" is.
6493 unsigned AtRegNo;
6494 const AsmToken &Reg = Parser.getTok();
6495 if (Reg.is(AsmToken::Identifier)) {
6496 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6497 } else if (Reg.is(AsmToken::Integer)) {
6498 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006499 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006500 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006501 return false;
6502 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006503
6504 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006505 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006506 reportParseError("invalid register");
6507 return false;
6508 }
6509 Parser.Lex(); // Eat "reg".
6510
6511 // If this is not the end of the statement, report an error.
6512 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6513 reportParseError("unexpected token, expected end of statement");
6514 return false;
6515 }
6516
6517 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6518
6519 Parser.Lex(); // Consume the EndOfStatement.
6520 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006521}
6522
6523bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006524 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006525 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006526 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006527 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006528 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006529 return false;
6530 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006531 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006532 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006533 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006534 return false;
6535}
6536
6537bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006538 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006539 Parser.Lex();
6540 // If this is not the end of the statement, report an error.
6541 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006542 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006543 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006544 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006545 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006546 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006547 Parser.Lex(); // Consume the EndOfStatement.
6548 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006549}
6550
6551bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006552 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006553 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006554 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006555 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006556 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006557 return false;
6558 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006559 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006560 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006561 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006562 return false;
6563}
6564
6565bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006566 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006567 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006568 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006569 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006570 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006571 return false;
6572 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006573 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006574 reportParseError("`noreorder' must be set before `nomacro'");
6575 return false;
6576 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006577 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006578 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006579 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006580 return false;
6581}
Jack Carterd76b2372013-03-21 21:44:16 +00006582
Daniel Sanders44934432014-08-07 12:03:36 +00006583bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006584 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006585 Parser.Lex();
6586
6587 // If this is not the end of the statement, report an error.
6588 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006589 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006590
6591 setFeatureBits(Mips::FeatureMSA, "msa");
6592 getTargetStreamer().emitDirectiveSetMsa();
6593 return false;
6594}
6595
6596bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006597 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006598 Parser.Lex();
6599
6600 // If this is not the end of the statement, report an error.
6601 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006602 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006603
6604 clearFeatureBits(Mips::FeatureMSA, "msa");
6605 getTargetStreamer().emitDirectiveSetNoMsa();
6606 return false;
6607}
6608
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006609bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006610 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006611 Parser.Lex(); // Eat "nodsp".
6612
6613 // If this is not the end of the statement, report an error.
6614 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6615 reportParseError("unexpected token, expected end of statement");
6616 return false;
6617 }
6618
6619 clearFeatureBits(Mips::FeatureDSP, "dsp");
6620 getTargetStreamer().emitDirectiveSetNoDsp();
6621 return false;
6622}
6623
Toma Tabacucc2502d2014-11-04 17:18:07 +00006624bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006625 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006626 Parser.Lex(); // Eat "mips16".
6627
Jack Carter39536722014-01-22 23:08:42 +00006628 // If this is not the end of the statement, report an error.
6629 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006630 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006631 return false;
6632 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006633
6634 setFeatureBits(Mips::FeatureMips16, "mips16");
6635 getTargetStreamer().emitDirectiveSetMips16();
6636 Parser.Lex(); // Consume the EndOfStatement.
6637 return false;
6638}
6639
6640bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006641 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006642 Parser.Lex(); // Eat "nomips16".
6643
6644 // If this is not the end of the statement, report an error.
6645 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6646 reportParseError("unexpected token, expected end of statement");
6647 return false;
6648 }
6649
6650 clearFeatureBits(Mips::FeatureMips16, "mips16");
6651 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006652 Parser.Lex(); // Consume the EndOfStatement.
6653 return false;
6654}
6655
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006656bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006657 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006658 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006659 // Line can be: .set fp=32
6660 // .set fp=xx
6661 // .set fp=64
6662 Parser.Lex(); // Eat fp token
6663 AsmToken Tok = Parser.getTok();
6664 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006665 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006666 return false;
6667 }
6668 Parser.Lex(); // Eat '=' token.
6669 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006670
6671 if (!parseFpABIValue(FpAbiVal, ".set"))
6672 return false;
6673
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006674 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006675 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006676 return false;
6677 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006678 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006679 Parser.Lex(); // Consume the EndOfStatement.
6680 return false;
6681}
6682
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006683bool MipsAsmParser::parseSetOddSPRegDirective() {
6684 MCAsmParser &Parser = getParser();
6685
6686 Parser.Lex(); // Eat "oddspreg".
6687 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6688 reportParseError("unexpected token, expected end of statement");
6689 return false;
6690 }
6691
6692 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6693 getTargetStreamer().emitDirectiveSetOddSPReg();
6694 return false;
6695}
6696
6697bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6698 MCAsmParser &Parser = getParser();
6699
6700 Parser.Lex(); // Eat "nooddspreg".
6701 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6702 reportParseError("unexpected token, expected end of statement");
6703 return false;
6704 }
6705
6706 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6707 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6708 return false;
6709}
6710
Simon Dardis805f1e02017-07-11 21:28:36 +00006711bool MipsAsmParser::parseSetMtDirective() {
6712 MCAsmParser &Parser = getParser();
6713 Parser.Lex(); // Eat "mt".
6714
6715 // If this is not the end of the statement, report an error.
6716 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6717 reportParseError("unexpected token, expected end of statement");
6718 return false;
6719 }
6720
6721 setFeatureBits(Mips::FeatureMT, "mt");
6722 getTargetStreamer().emitDirectiveSetMt();
6723 Parser.Lex(); // Consume the EndOfStatement.
6724 return false;
6725}
6726
6727bool MipsAsmParser::parseSetNoMtDirective() {
6728 MCAsmParser &Parser = getParser();
6729 Parser.Lex(); // Eat "nomt".
6730
6731 // If this is not the end of the statement, report an error.
6732 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6733 reportParseError("unexpected token, expected end of statement");
6734 return false;
6735 }
6736
6737 clearFeatureBits(Mips::FeatureMT, "mt");
6738
6739 getTargetStreamer().emitDirectiveSetNoMt();
6740 Parser.Lex(); // Consume the EndOfStatement.
6741 return false;
6742}
6743
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006744bool MipsAsmParser::parseSetNoCRCDirective() {
6745 MCAsmParser &Parser = getParser();
6746 Parser.Lex(); // Eat "nocrc".
6747
6748 // If this is not the end of the statement, report an error.
6749 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6750 reportParseError("unexpected token, expected end of statement");
6751 return false;
6752 }
6753
6754 clearFeatureBits(Mips::FeatureCRC, "crc");
6755
6756 getTargetStreamer().emitDirectiveSetNoCRC();
6757 Parser.Lex(); // Consume the EndOfStatement.
6758 return false;
6759}
6760
Petar Jovanovicd4349f32018-04-27 09:12:08 +00006761bool MipsAsmParser::parseSetNoVirtDirective() {
6762 MCAsmParser &Parser = getParser();
6763 Parser.Lex(); // Eat "novirt".
6764
6765 // If this is not the end of the statement, report an error.
6766 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6767 reportParseError("unexpected token, expected end of statement");
6768 return false;
6769 }
6770
6771 clearFeatureBits(Mips::FeatureVirt, "virt");
6772
6773 getTargetStreamer().emitDirectiveSetNoVirt();
6774 Parser.Lex(); // Consume the EndOfStatement.
6775 return false;
6776}
6777
Petar Jovanovicdaf51692018-05-17 16:30:32 +00006778bool MipsAsmParser::parseSetNoGINVDirective() {
6779 MCAsmParser &Parser = getParser();
6780 Parser.Lex(); // Eat "noginv".
6781
6782 // If this is not the end of the statement, report an error.
6783 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6784 reportParseError("unexpected token, expected end of statement");
6785 return false;
6786 }
6787
6788 clearFeatureBits(Mips::FeatureGINV, "ginv");
6789
6790 getTargetStreamer().emitDirectiveSetNoGINV();
6791 Parser.Lex(); // Consume the EndOfStatement.
6792 return false;
6793}
6794
Toma Tabacu9db22db2014-09-09 10:15:38 +00006795bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006796 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006797 SMLoc Loc = getLexer().getLoc();
6798
6799 Parser.Lex();
6800 if (getLexer().isNot(AsmToken::EndOfStatement))
6801 return reportParseError("unexpected token, expected end of statement");
6802
6803 // Always keep an element on the options "stack" to prevent the user
6804 // from changing the initial options. This is how we remember them.
6805 if (AssemblerOptions.size() == 2)
6806 return reportParseError(Loc, ".set pop with no .set push");
6807
Akira Hatanakab11ef082015-11-14 06:35:56 +00006808 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006809 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006810 setAvailableFeatures(
6811 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6812 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006813
6814 getTargetStreamer().emitDirectiveSetPop();
6815 return false;
6816}
6817
6818bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006819 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006820 Parser.Lex();
6821 if (getLexer().isNot(AsmToken::EndOfStatement))
6822 return reportParseError("unexpected token, expected end of statement");
6823
6824 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006825 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006826 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006827
6828 getTargetStreamer().emitDirectiveSetPush();
6829 return false;
6830}
6831
Toma Tabacu29696502015-06-02 09:48:04 +00006832bool MipsAsmParser::parseSetSoftFloatDirective() {
6833 MCAsmParser &Parser = getParser();
6834 Parser.Lex();
6835 if (getLexer().isNot(AsmToken::EndOfStatement))
6836 return reportParseError("unexpected token, expected end of statement");
6837
6838 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6839 getTargetStreamer().emitDirectiveSetSoftFloat();
6840 return false;
6841}
6842
6843bool MipsAsmParser::parseSetHardFloatDirective() {
6844 MCAsmParser &Parser = getParser();
6845 Parser.Lex();
6846 if (getLexer().isNot(AsmToken::EndOfStatement))
6847 return reportParseError("unexpected token, expected end of statement");
6848
6849 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6850 getTargetStreamer().emitDirectiveSetHardFloat();
6851 return false;
6852}
6853
Jack Carterd76b2372013-03-21 21:44:16 +00006854bool MipsAsmParser::parseSetAssignment() {
6855 StringRef Name;
6856 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006857 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006858
6859 if (Parser.parseIdentifier(Name))
Simon Atanasyan3535cb12018-05-29 09:51:22 +00006860 return reportParseError("expected identifier after .set");
Jack Carterd76b2372013-03-21 21:44:16 +00006861
6862 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006863 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006864 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006865
Simon Atanasyan69301c92018-05-29 15:58:06 +00006866 if (getLexer().is(AsmToken::Dollar) &&
6867 getLexer().peekTok().is(AsmToken::Integer)) {
6868 // Parse assignment of a numeric register:
6869 // .set r1,$1
6870 Parser.Lex(); // Eat $.
6871 RegisterSets[Name] = Parser.getTok();
6872 Parser.Lex(); // Eat identifier.
6873 getContext().getOrCreateSymbol(Name);
6874 } else if (!Parser.parseExpression(Value)) {
6875 // Parse assignment of an expression including
6876 // symbolic registers:
6877 // .set $tmp, $BB0-$BB1
6878 // .set r2, $f2
6879 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
6880 Sym->setVariableValue(Value);
6881 } else {
Jack Carter02593002013-05-28 22:21:05 +00006882 return reportParseError("expected valid expression after comma");
Simon Atanasyan69301c92018-05-29 15:58:06 +00006883 }
Jack Carterd76b2372013-03-21 21:44:16 +00006884
6885 return false;
6886}
Jack Carterd0bd6422013-04-18 00:41:53 +00006887
Toma Tabacu26647792014-09-09 12:52:14 +00006888bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006889 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006890 Parser.Lex();
6891 if (getLexer().isNot(AsmToken::EndOfStatement))
6892 return reportParseError("unexpected token, expected end of statement");
6893
6894 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006895 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006896 setAvailableFeatures(
6897 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6898 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006899 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6900
6901 getTargetStreamer().emitDirectiveSetMips0();
6902 return false;
6903}
6904
Toma Tabacu85618b32014-08-19 14:22:52 +00006905bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006906 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006907 Parser.Lex();
6908 if (getLexer().isNot(AsmToken::Equal))
6909 return reportParseError("unexpected token, expected equals sign");
6910
6911 Parser.Lex();
6912 StringRef Arch;
6913 if (Parser.parseIdentifier(Arch))
6914 return reportParseError("expected arch identifier");
6915
6916 StringRef ArchFeatureName =
6917 StringSwitch<StringRef>(Arch)
6918 .Case("mips1", "mips1")
6919 .Case("mips2", "mips2")
6920 .Case("mips3", "mips3")
6921 .Case("mips4", "mips4")
6922 .Case("mips5", "mips5")
6923 .Case("mips32", "mips32")
6924 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006925 .Case("mips32r3", "mips32r3")
6926 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006927 .Case("mips32r6", "mips32r6")
6928 .Case("mips64", "mips64")
6929 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006930 .Case("mips64r3", "mips64r3")
6931 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006932 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006933 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006934 .Case("r4000", "mips3") // This is an implementation of Mips3.
6935 .Default("");
6936
6937 if (ArchFeatureName.empty())
6938 return reportParseError("unsupported architecture");
6939
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00006940 if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
6941 return reportParseError("mips64r6 does not support microMIPS");
6942
Toma Tabacu85618b32014-08-19 14:22:52 +00006943 selectArch(ArchFeatureName);
6944 getTargetStreamer().emitDirectiveSetArch(Arch);
6945 return false;
6946}
6947
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006948bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006949 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006950 Parser.Lex();
6951 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006952 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006953
Matheus Almeida2852af82014-04-22 10:15:54 +00006954 switch (Feature) {
6955 default:
6956 llvm_unreachable("Unimplemented feature");
6957 case Mips::FeatureDSP:
6958 setFeatureBits(Mips::FeatureDSP, "dsp");
6959 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006960 break;
Petar Jovanovic65f10242017-10-05 17:40:32 +00006961 case Mips::FeatureDSPR2:
6962 setFeatureBits(Mips::FeatureDSPR2, "dspr2");
6963 getTargetStreamer().emitDirectiveSetDspr2();
6964 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006965 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006966 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006967 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006968 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006969 case Mips::FeatureMips1:
6970 selectArch("mips1");
6971 getTargetStreamer().emitDirectiveSetMips1();
6972 break;
6973 case Mips::FeatureMips2:
6974 selectArch("mips2");
6975 getTargetStreamer().emitDirectiveSetMips2();
6976 break;
6977 case Mips::FeatureMips3:
6978 selectArch("mips3");
6979 getTargetStreamer().emitDirectiveSetMips3();
6980 break;
6981 case Mips::FeatureMips4:
6982 selectArch("mips4");
6983 getTargetStreamer().emitDirectiveSetMips4();
6984 break;
6985 case Mips::FeatureMips5:
6986 selectArch("mips5");
6987 getTargetStreamer().emitDirectiveSetMips5();
6988 break;
6989 case Mips::FeatureMips32:
6990 selectArch("mips32");
6991 getTargetStreamer().emitDirectiveSetMips32();
6992 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006993 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006994 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006995 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006996 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006997 case Mips::FeatureMips32r3:
6998 selectArch("mips32r3");
6999 getTargetStreamer().emitDirectiveSetMips32R3();
7000 break;
7001 case Mips::FeatureMips32r5:
7002 selectArch("mips32r5");
7003 getTargetStreamer().emitDirectiveSetMips32R5();
7004 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00007005 case Mips::FeatureMips32r6:
7006 selectArch("mips32r6");
7007 getTargetStreamer().emitDirectiveSetMips32R6();
7008 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00007009 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00007010 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00007011 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00007012 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00007013 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00007014 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00007015 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00007016 break;
Daniel Sanders17793142015-02-18 16:24:50 +00007017 case Mips::FeatureMips64r3:
7018 selectArch("mips64r3");
7019 getTargetStreamer().emitDirectiveSetMips64R3();
7020 break;
7021 case Mips::FeatureMips64r5:
7022 selectArch("mips64r5");
7023 getTargetStreamer().emitDirectiveSetMips64R5();
7024 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00007025 case Mips::FeatureMips64r6:
7026 selectArch("mips64r6");
7027 getTargetStreamer().emitDirectiveSetMips64R6();
7028 break;
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007029 case Mips::FeatureCRC:
7030 setFeatureBits(Mips::FeatureCRC, "crc");
7031 getTargetStreamer().emitDirectiveSetCRC();
7032 break;
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007033 case Mips::FeatureVirt:
7034 setFeatureBits(Mips::FeatureVirt, "virt");
7035 getTargetStreamer().emitDirectiveSetVirt();
7036 break;
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007037 case Mips::FeatureGINV:
7038 setFeatureBits(Mips::FeatureGINV, "ginv");
7039 getTargetStreamer().emitDirectiveSetGINV();
7040 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00007041 }
7042 return false;
7043}
7044
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007045bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007046 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007047 if (getLexer().isNot(AsmToken::Comma)) {
7048 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007049 return Error(Loc, ErrorStr);
7050 }
7051
Matheus Almeida2852af82014-04-22 10:15:54 +00007052 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007053 return true;
7054}
7055
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007056// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
7057// In this class, it is only used for .cprestore.
7058// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
7059// MipsTargetELFStreamer and MipsAsmParser.
7060bool MipsAsmParser::isPicAndNotNxxAbi() {
7061 return inPicMode() && !(isABI_N32() || isABI_N64());
7062}
7063
Toma Tabacuc4c202a2014-10-01 14:53:19 +00007064bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00007065 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00007066 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007067
Toma Tabacudde4c462014-11-06 10:02:45 +00007068 if (inMips16Mode()) {
7069 reportParseError(".cpload is not supported in Mips16 mode");
7070 return false;
7071 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007072
David Blaikie960ea3f2014-06-08 16:18:35 +00007073 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00007074 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007075 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7076 reportParseError("expected register containing function address");
7077 return false;
7078 }
7079
David Blaikie960ea3f2014-06-08 16:18:35 +00007080 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
7081 if (!RegOpnd.isGPRAsmReg()) {
7082 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007083 return false;
7084 }
7085
Toma Tabacudde4c462014-11-06 10:02:45 +00007086 // If this is not the end of the statement, report an error.
7087 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7088 reportParseError("unexpected token, expected end of statement");
7089 return false;
7090 }
7091
Toma Tabacuc4c202a2014-10-01 14:53:19 +00007092 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007093 return false;
7094}
7095
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007096bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
7097 MCAsmParser &Parser = getParser();
7098
7099 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
7100 // is used in non-PIC mode.
7101
7102 if (inMips16Mode()) {
7103 reportParseError(".cprestore is not supported in Mips16 mode");
7104 return false;
7105 }
7106
7107 // Get the stack offset value.
7108 const MCExpr *StackOffset;
7109 int64_t StackOffsetVal;
7110 if (Parser.parseExpression(StackOffset)) {
7111 reportParseError("expected stack offset value");
7112 return false;
7113 }
7114
7115 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
7116 reportParseError("stack offset is not an absolute expression");
7117 return false;
7118 }
7119
7120 if (StackOffsetVal < 0) {
7121 Warning(Loc, ".cprestore with negative stack offset has no effect");
7122 IsCpRestoreSet = false;
7123 } else {
7124 IsCpRestoreSet = true;
7125 CpRestoreOffset = StackOffsetVal;
7126 }
7127
7128 // If this is not the end of the statement, report an error.
7129 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7130 reportParseError("unexpected token, expected end of statement");
7131 return false;
7132 }
7133
Daniel Sandersdf8510d2016-05-11 12:48:19 +00007134 if (!getTargetStreamer().emitDirectiveCpRestore(
7135 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00007136 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007137 Parser.Lex(); // Consume the EndOfStatement.
7138 return false;
7139}
7140
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007141bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007142 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007143 unsigned FuncReg;
7144 unsigned Save;
7145 bool SaveIsReg = true;
7146
Matheus Almeida7e815762014-06-18 13:08:59 +00007147 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007148 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007149 if (ResTy == MatchOperand_NoMatch) {
7150 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00007151 return false;
7152 }
7153
7154 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7155 if (!FuncRegOpnd.isGPRAsmReg()) {
7156 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007157 return false;
7158 }
7159
7160 FuncReg = FuncRegOpnd.getGPR32Reg();
7161 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007162
Toma Tabacu65f10572014-09-16 15:00:52 +00007163 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007164 return true;
7165
Toma Tabacu13964452014-09-04 13:23:44 +00007166 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007167 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00007168 const MCExpr *OffsetExpr;
7169 int64_t OffsetVal;
7170 SMLoc ExprLoc = getLexer().getLoc();
7171
7172 if (Parser.parseExpression(OffsetExpr) ||
7173 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
7174 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00007175 return false;
7176 }
Daniel Sanders5d796282015-09-21 09:26:55 +00007177
7178 Save = OffsetVal;
7179 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00007180 } else {
7181 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7182 if (!SaveOpnd.isGPRAsmReg()) {
7183 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007184 return false;
7185 }
7186 Save = SaveOpnd.getGPR32Reg();
7187 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007188
Toma Tabacu65f10572014-09-16 15:00:52 +00007189 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007190 return true;
7191
Toma Tabacu8874eac2015-02-18 13:46:53 +00007192 const MCExpr *Expr;
7193 if (Parser.parseExpression(Expr)) {
7194 reportParseError("expected expression");
7195 return false;
7196 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007197
Toma Tabacu8874eac2015-02-18 13:46:53 +00007198 if (Expr->getKind() != MCExpr::SymbolRef) {
7199 reportParseError("expected symbol");
7200 return false;
7201 }
7202 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
7203
Daniel Sandersf173dda2015-09-22 10:50:09 +00007204 CpSaveLocation = Save;
7205 CpSaveLocationIsRegister = SaveIsReg;
7206
Toma Tabacu8874eac2015-02-18 13:46:53 +00007207 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
7208 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007209 return false;
7210}
7211
Daniel Sandersf173dda2015-09-22 10:50:09 +00007212bool MipsAsmParser::parseDirectiveCPReturn() {
7213 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
7214 CpSaveLocationIsRegister);
7215 return false;
7216}
7217
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007218bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007219 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007220 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7221 const AsmToken &Tok = Parser.getTok();
7222
7223 if (Tok.getString() == "2008") {
7224 Parser.Lex();
7225 getTargetStreamer().emitDirectiveNaN2008();
7226 return false;
7227 } else if (Tok.getString() == "legacy") {
7228 Parser.Lex();
7229 getTargetStreamer().emitDirectiveNaNLegacy();
7230 return false;
7231 }
7232 }
7233 // If we don't recognize the option passed to the .nan
7234 // directive (e.g. no option or unknown option), emit an error.
7235 reportParseError("invalid option in .nan directive");
7236 return false;
7237}
7238
Jack Carter0b744b32012-10-04 02:29:46 +00007239bool MipsAsmParser::parseDirectiveSet() {
Simon Atanasyand408ec42018-05-29 09:51:28 +00007240 const AsmToken &Tok = getParser().getTok();
7241 StringRef IdVal = Tok.getString();
7242 SMLoc Loc = Tok.getLoc();
Jack Carter0b744b32012-10-04 02:29:46 +00007243
Simon Atanasyand408ec42018-05-29 09:51:28 +00007244 if (IdVal == "noat")
Jack Carter0b744b32012-10-04 02:29:46 +00007245 return parseSetNoAtDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007246 if (IdVal == "at")
Jack Carter0b744b32012-10-04 02:29:46 +00007247 return parseSetAtDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007248 if (IdVal == "arch")
Toma Tabacu85618b32014-08-19 14:22:52 +00007249 return parseSetArchDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007250 if (IdVal == "bopt") {
7251 Warning(Loc, "'bopt' feature is unsupported");
Simon Dardisac9c30c2017-02-01 18:50:24 +00007252 getParser().Lex();
7253 return false;
Simon Atanasyand408ec42018-05-29 09:51:28 +00007254 }
7255 if (IdVal == "nobopt") {
Simon Dardisac9c30c2017-02-01 18:50:24 +00007256 // We're already running in nobopt mode, so nothing to do.
7257 getParser().Lex();
7258 return false;
Simon Atanasyand408ec42018-05-29 09:51:28 +00007259 }
7260 if (IdVal == "fp")
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007261 return parseSetFpDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007262 if (IdVal == "oddspreg")
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007263 return parseSetOddSPRegDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007264 if (IdVal == "nooddspreg")
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007265 return parseSetNoOddSPRegDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007266 if (IdVal == "pop")
Toma Tabacu9db22db2014-09-09 10:15:38 +00007267 return parseSetPopDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007268 if (IdVal == "push")
Toma Tabacu9db22db2014-09-09 10:15:38 +00007269 return parseSetPushDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007270 if (IdVal == "reorder")
Jack Carter0b744b32012-10-04 02:29:46 +00007271 return parseSetReorderDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007272 if (IdVal == "noreorder")
Jack Carter0b744b32012-10-04 02:29:46 +00007273 return parseSetNoReorderDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007274 if (IdVal == "macro")
Jack Carter0b744b32012-10-04 02:29:46 +00007275 return parseSetMacroDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007276 if (IdVal == "nomacro")
Jack Carter0b744b32012-10-04 02:29:46 +00007277 return parseSetNoMacroDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007278 if (IdVal == "mips16")
Toma Tabacucc2502d2014-11-04 17:18:07 +00007279 return parseSetMips16Directive();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007280 if (IdVal == "nomips16")
Jack Carter39536722014-01-22 23:08:42 +00007281 return parseSetNoMips16Directive();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007282 if (IdVal == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00007283 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007284 getTargetStreamer().emitDirectiveSetNoMicroMips();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007285 getParser().eatToEndOfStatement();
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007286 return false;
Simon Atanasyand408ec42018-05-29 09:51:28 +00007287 }
7288 if (IdVal == "micromips") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007289 if (hasMips64r6()) {
Simon Atanasyand408ec42018-05-29 09:51:28 +00007290 Error(Loc, ".set micromips directive is not supported with MIPS64R6");
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007291 return false;
7292 }
Matheus Almeida2852af82014-04-22 10:15:54 +00007293 return parseSetFeature(Mips::FeatureMicroMips);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007294 }
7295 if (IdVal == "mips0")
Toma Tabacu26647792014-09-09 12:52:14 +00007296 return parseSetMips0Directive();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007297 if (IdVal == "mips1")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007298 return parseSetFeature(Mips::FeatureMips1);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007299 if (IdVal == "mips2")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007300 return parseSetFeature(Mips::FeatureMips2);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007301 if (IdVal == "mips3")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007302 return parseSetFeature(Mips::FeatureMips3);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007303 if (IdVal == "mips4")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007304 return parseSetFeature(Mips::FeatureMips4);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007305 if (IdVal == "mips5")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007306 return parseSetFeature(Mips::FeatureMips5);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007307 if (IdVal == "mips32")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007308 return parseSetFeature(Mips::FeatureMips32);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007309 if (IdVal == "mips32r2")
Matheus Almeida2852af82014-04-22 10:15:54 +00007310 return parseSetFeature(Mips::FeatureMips32r2);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007311 if (IdVal == "mips32r3")
Daniel Sanders17793142015-02-18 16:24:50 +00007312 return parseSetFeature(Mips::FeatureMips32r3);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007313 if (IdVal == "mips32r5")
Daniel Sanders17793142015-02-18 16:24:50 +00007314 return parseSetFeature(Mips::FeatureMips32r5);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007315 if (IdVal == "mips32r6")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007316 return parseSetFeature(Mips::FeatureMips32r6);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007317 if (IdVal == "mips64")
Matheus Almeida2852af82014-04-22 10:15:54 +00007318 return parseSetFeature(Mips::FeatureMips64);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007319 if (IdVal == "mips64r2")
Matheus Almeida2852af82014-04-22 10:15:54 +00007320 return parseSetFeature(Mips::FeatureMips64r2);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007321 if (IdVal == "mips64r3")
Daniel Sanders17793142015-02-18 16:24:50 +00007322 return parseSetFeature(Mips::FeatureMips64r3);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007323 if (IdVal == "mips64r5")
Daniel Sanders17793142015-02-18 16:24:50 +00007324 return parseSetFeature(Mips::FeatureMips64r5);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007325 if (IdVal == "mips64r6") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007326 if (inMicroMipsMode()) {
Simon Atanasyand408ec42018-05-29 09:51:28 +00007327 Error(Loc, "MIPS64R6 is not supported with microMIPS");
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007328 return false;
7329 }
Daniel Sandersf0df2212014-08-04 12:20:00 +00007330 return parseSetFeature(Mips::FeatureMips64r6);
Jack Carter0b744b32012-10-04 02:29:46 +00007331 }
Simon Atanasyand408ec42018-05-29 09:51:28 +00007332 if (IdVal == "dsp")
7333 return parseSetFeature(Mips::FeatureDSP);
7334 if (IdVal == "dspr2")
7335 return parseSetFeature(Mips::FeatureDSPR2);
7336 if (IdVal == "nodsp")
7337 return parseSetNoDspDirective();
7338 if (IdVal == "msa")
7339 return parseSetMsaDirective();
7340 if (IdVal == "nomsa")
7341 return parseSetNoMsaDirective();
7342 if (IdVal == "mt")
7343 return parseSetMtDirective();
7344 if (IdVal == "nomt")
7345 return parseSetNoMtDirective();
7346 if (IdVal == "softfloat")
7347 return parseSetSoftFloatDirective();
7348 if (IdVal == "hardfloat")
7349 return parseSetHardFloatDirective();
7350 if (IdVal == "crc")
7351 return parseSetFeature(Mips::FeatureCRC);
7352 if (IdVal == "nocrc")
7353 return parseSetNoCRCDirective();
7354 if (IdVal == "virt")
7355 return parseSetFeature(Mips::FeatureVirt);
7356 if (IdVal == "novirt")
7357 return parseSetNoVirtDirective();
7358 if (IdVal == "ginv")
7359 return parseSetFeature(Mips::FeatureGINV);
7360 if (IdVal == "noginv")
7361 return parseSetNoGINVDirective();
Jack Carter07c818d2013-01-25 01:31:34 +00007362
Simon Atanasyand408ec42018-05-29 09:51:28 +00007363 // It is just an identifier, look for an assignment.
7364 return parseSetAssignment();
Jack Carter0b744b32012-10-04 02:29:46 +00007365}
7366
Vladimir Medic4c299852013-11-06 11:27:05 +00007367/// parseDirectiveGpWord
7368/// ::= .gpword local_sym
7369bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007370 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00007371 const MCExpr *Value;
7372 // EmitGPRel32Value requires an expression, so we are using base class
7373 // method to evaluate the expression.
7374 if (getParser().parseExpression(Value))
7375 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00007376 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00007377
Vladimir Medice10c1122013-11-13 13:18:04 +00007378 if (getLexer().isNot(AsmToken::EndOfStatement))
Fangrui Songf78650a2018-07-30 19:41:25 +00007379 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007380 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00007381 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00007382 return false;
7383}
7384
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007385/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00007386/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007387bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007388 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007389 const MCExpr *Value;
7390 // EmitGPRel64Value requires an expression, so we are using base class
7391 // method to evaluate the expression.
7392 if (getParser().parseExpression(Value))
7393 return true;
7394 getParser().getStreamer().EmitGPRel64Value(Value);
7395
7396 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007397 return Error(getLexer().getLoc(),
7398 "unexpected token, expected end of statement");
7399 Parser.Lex(); // Eat EndOfStatement token.
7400 return false;
7401}
7402
7403/// parseDirectiveDtpRelWord
7404/// ::= .dtprelword tls_sym
7405bool MipsAsmParser::parseDirectiveDtpRelWord() {
7406 MCAsmParser &Parser = getParser();
7407 const MCExpr *Value;
7408 // EmitDTPRel32Value requires an expression, so we are using base class
7409 // method to evaluate the expression.
7410 if (getParser().parseExpression(Value))
7411 return true;
7412 getParser().getStreamer().EmitDTPRel32Value(Value);
7413
7414 if (getLexer().isNot(AsmToken::EndOfStatement))
7415 return Error(getLexer().getLoc(),
7416 "unexpected token, expected end of statement");
7417 Parser.Lex(); // Eat EndOfStatement token.
7418 return false;
7419}
7420
7421/// parseDirectiveDtpRelDWord
7422/// ::= .dtpreldword tls_sym
7423bool MipsAsmParser::parseDirectiveDtpRelDWord() {
7424 MCAsmParser &Parser = getParser();
7425 const MCExpr *Value;
7426 // EmitDTPRel64Value requires an expression, so we are using base class
7427 // method to evaluate the expression.
7428 if (getParser().parseExpression(Value))
7429 return true;
7430 getParser().getStreamer().EmitDTPRel64Value(Value);
7431
7432 if (getLexer().isNot(AsmToken::EndOfStatement))
7433 return Error(getLexer().getLoc(),
7434 "unexpected token, expected end of statement");
7435 Parser.Lex(); // Eat EndOfStatement token.
7436 return false;
7437}
7438
7439/// parseDirectiveTpRelWord
7440/// ::= .tprelword tls_sym
7441bool MipsAsmParser::parseDirectiveTpRelWord() {
7442 MCAsmParser &Parser = getParser();
7443 const MCExpr *Value;
7444 // EmitTPRel32Value requires an expression, so we are using base class
7445 // method to evaluate the expression.
7446 if (getParser().parseExpression(Value))
7447 return true;
7448 getParser().getStreamer().EmitTPRel32Value(Value);
7449
7450 if (getLexer().isNot(AsmToken::EndOfStatement))
7451 return Error(getLexer().getLoc(),
7452 "unexpected token, expected end of statement");
7453 Parser.Lex(); // Eat EndOfStatement token.
7454 return false;
7455}
7456
7457/// parseDirectiveTpRelDWord
7458/// ::= .tpreldword tls_sym
7459bool MipsAsmParser::parseDirectiveTpRelDWord() {
7460 MCAsmParser &Parser = getParser();
7461 const MCExpr *Value;
7462 // EmitTPRel64Value requires an expression, so we are using base class
7463 // method to evaluate the expression.
7464 if (getParser().parseExpression(Value))
7465 return true;
7466 getParser().getStreamer().EmitTPRel64Value(Value);
7467
7468 if (getLexer().isNot(AsmToken::EndOfStatement))
7469 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007470 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00007471 Parser.Lex(); // Eat EndOfStatement token.
7472 return false;
7473}
7474
Jack Carter0cd3c192014-01-06 23:27:31 +00007475bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007476 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00007477 // Get the option token.
7478 AsmToken Tok = Parser.getTok();
7479 // At the moment only identifiers are supported.
7480 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007481 return Error(Parser.getTok().getLoc(),
7482 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00007483 }
7484
7485 StringRef Option = Tok.getIdentifier();
7486
7487 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007488 // MipsAsmParser needs to know if the current PIC mode changes.
7489 IsPicEnabled = false;
7490
Jack Carter0cd3c192014-01-06 23:27:31 +00007491 getTargetStreamer().emitDirectiveOptionPic0();
7492 Parser.Lex();
7493 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007494 return Error(Parser.getTok().getLoc(),
7495 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007496 }
7497 return false;
7498 }
7499
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007500 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007501 // MipsAsmParser needs to know if the current PIC mode changes.
7502 IsPicEnabled = true;
7503
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007504 getTargetStreamer().emitDirectiveOptionPic2();
7505 Parser.Lex();
7506 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007507 return Error(Parser.getTok().getLoc(),
7508 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007509 }
7510 return false;
7511 }
7512
Jack Carter0cd3c192014-01-06 23:27:31 +00007513 // Unknown option.
Fangrui Songf78650a2018-07-30 19:41:25 +00007514 Warning(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007515 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007516 Parser.eatToEndOfStatement();
7517 return false;
7518}
7519
Toma Tabacu9ca50962015-04-16 09:53:47 +00007520/// parseInsnDirective
7521/// ::= .insn
7522bool MipsAsmParser::parseInsnDirective() {
7523 // If this is not the end of the statement, report an error.
7524 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7525 reportParseError("unexpected token, expected end of statement");
7526 return false;
7527 }
7528
7529 // The actual label marking happens in
7530 // MipsELFStreamer::createPendingLabelRelocs().
7531 getTargetStreamer().emitDirectiveInsn();
7532
7533 getParser().Lex(); // Eat EndOfStatement token.
7534 return false;
7535}
7536
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007537/// parseRSectionDirective
7538/// ::= .rdata
7539bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
7540 // If this is not the end of the statement, report an error.
7541 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7542 reportParseError("unexpected token, expected end of statement");
7543 return false;
7544 }
7545
7546 MCSection *ELFSection = getContext().getELFSection(
7547 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7548 getParser().getStreamer().SwitchSection(ELFSection);
7549
7550 getParser().Lex(); // Eat EndOfStatement token.
7551 return false;
7552}
7553
Simon Atanasyanbe186202016-02-11 06:45:54 +00007554/// parseSSectionDirective
7555/// ::= .sbss
7556/// ::= .sdata
7557bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7558 // If this is not the end of the statement, report an error.
7559 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7560 reportParseError("unexpected token, expected end of statement");
7561 return false;
7562 }
7563
7564 MCSection *ELFSection = getContext().getELFSection(
7565 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7566 getParser().getStreamer().SwitchSection(ELFSection);
7567
7568 getParser().Lex(); // Eat EndOfStatement token.
7569 return false;
7570}
7571
Daniel Sanders7e527422014-07-10 13:38:23 +00007572/// parseDirectiveModule
7573/// ::= .module oddspreg
7574/// ::= .module nooddspreg
7575/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007576/// ::= .module softfloat
7577/// ::= .module hardfloat
Simon Dardis805f1e02017-07-11 21:28:36 +00007578/// ::= .module mt
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007579/// ::= .module crc
7580/// ::= .module nocrc
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007581/// ::= .module virt
7582/// ::= .module novirt
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007583/// ::= .module ginv
7584/// ::= .module noginv
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007585bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007586 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007587 MCAsmLexer &Lexer = getLexer();
7588 SMLoc L = Lexer.getLoc();
7589
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007590 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007591 // TODO : get a better message.
7592 reportParseError(".module directive must appear before any code");
7593 return false;
7594 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007595
Toma Tabacuc405c822015-01-23 10:40:19 +00007596 StringRef Option;
7597 if (Parser.parseIdentifier(Option)) {
7598 reportParseError("expected .module option identifier");
7599 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007600 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007601
Toma Tabacuc405c822015-01-23 10:40:19 +00007602 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007603 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007604
Toma Tabacu3c499582015-06-25 10:56:57 +00007605 // Synchronize the abiflags information with the FeatureBits information we
7606 // changed above.
7607 getTargetStreamer().updateABIInfo(*this);
7608
7609 // If printing assembly, use the recently updated abiflags information.
7610 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7611 // emitted at the end).
7612 getTargetStreamer().emitDirectiveModuleOddSPReg();
7613
Toma Tabacuc405c822015-01-23 10:40:19 +00007614 // If this is not the end of the statement, report an error.
7615 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7616 reportParseError("unexpected token, expected end of statement");
7617 return false;
7618 }
7619
7620 return false; // parseDirectiveModule has finished successfully.
7621 } else if (Option == "nooddspreg") {
7622 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007623 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007624 }
7625
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007626 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007627
Toma Tabacu3c499582015-06-25 10:56:57 +00007628 // Synchronize the abiflags information with the FeatureBits information we
7629 // changed above.
7630 getTargetStreamer().updateABIInfo(*this);
7631
7632 // If printing assembly, use the recently updated abiflags information.
7633 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7634 // emitted at the end).
7635 getTargetStreamer().emitDirectiveModuleOddSPReg();
7636
Toma Tabacuc405c822015-01-23 10:40:19 +00007637 // If this is not the end of the statement, report an error.
7638 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7639 reportParseError("unexpected token, expected end of statement");
7640 return false;
7641 }
7642
7643 return false; // parseDirectiveModule has finished successfully.
7644 } else if (Option == "fp") {
7645 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007646 } else if (Option == "softfloat") {
7647 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7648
7649 // Synchronize the ABI Flags information with the FeatureBits information we
7650 // updated above.
7651 getTargetStreamer().updateABIInfo(*this);
7652
7653 // If printing assembly, use the recently updated ABI Flags information.
7654 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7655 // emitted later).
7656 getTargetStreamer().emitDirectiveModuleSoftFloat();
7657
7658 // If this is not the end of the statement, report an error.
7659 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7660 reportParseError("unexpected token, expected end of statement");
7661 return false;
7662 }
7663
7664 return false; // parseDirectiveModule has finished successfully.
7665 } else if (Option == "hardfloat") {
7666 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7667
7668 // Synchronize the ABI Flags information with the FeatureBits information we
7669 // updated above.
7670 getTargetStreamer().updateABIInfo(*this);
7671
7672 // If printing assembly, use the recently updated ABI Flags information.
7673 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7674 // emitted later).
7675 getTargetStreamer().emitDirectiveModuleHardFloat();
7676
7677 // If this is not the end of the statement, report an error.
7678 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7679 reportParseError("unexpected token, expected end of statement");
7680 return false;
7681 }
7682
7683 return false; // parseDirectiveModule has finished successfully.
Simon Dardis805f1e02017-07-11 21:28:36 +00007684 } else if (Option == "mt") {
7685 setModuleFeatureBits(Mips::FeatureMT, "mt");
7686
7687 // Synchronize the ABI Flags information with the FeatureBits information we
7688 // updated above.
7689 getTargetStreamer().updateABIInfo(*this);
7690
Simon Dardisd9611922017-07-11 21:36:58 +00007691 // If printing assembly, use the recently updated ABI Flags information.
Simon Dardis805f1e02017-07-11 21:28:36 +00007692 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7693 // emitted later).
7694 getTargetStreamer().emitDirectiveModuleMT();
7695
7696 // If this is not the end of the statement, report an error.
7697 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7698 reportParseError("unexpected token, expected end of statement");
7699 return false;
7700 }
7701
7702 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007703 } else if (Option == "crc") {
7704 setModuleFeatureBits(Mips::FeatureCRC, "crc");
7705
7706 // Synchronize the ABI Flags information with the FeatureBits information we
7707 // updated above.
7708 getTargetStreamer().updateABIInfo(*this);
7709
7710 // If printing assembly, use the recently updated ABI Flags information.
7711 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7712 // emitted later).
7713 getTargetStreamer().emitDirectiveModuleCRC();
7714
7715 // If this is not the end of the statement, report an error.
7716 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7717 reportParseError("unexpected token, expected end of statement");
7718 return false;
7719 }
7720
7721 return false; // parseDirectiveModule has finished successfully.
7722 } else if (Option == "nocrc") {
7723 clearModuleFeatureBits(Mips::FeatureCRC, "crc");
7724
7725 // Synchronize the ABI Flags information with the FeatureBits information we
7726 // updated above.
7727 getTargetStreamer().updateABIInfo(*this);
7728
7729 // If printing assembly, use the recently updated ABI Flags information.
7730 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7731 // emitted later).
7732 getTargetStreamer().emitDirectiveModuleNoCRC();
7733
7734 // If this is not the end of the statement, report an error.
7735 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7736 reportParseError("unexpected token, expected end of statement");
7737 return false;
7738 }
7739
7740 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007741 } else if (Option == "virt") {
7742 setModuleFeatureBits(Mips::FeatureVirt, "virt");
7743
7744 // Synchronize the ABI Flags information with the FeatureBits information we
7745 // updated above.
7746 getTargetStreamer().updateABIInfo(*this);
7747
7748 // If printing assembly, use the recently updated ABI Flags information.
7749 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7750 // emitted later).
7751 getTargetStreamer().emitDirectiveModuleVirt();
7752
7753 // If this is not the end of the statement, report an error.
7754 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7755 reportParseError("unexpected token, expected end of statement");
7756 return false;
7757 }
7758
7759 return false; // parseDirectiveModule has finished successfully.
7760 } else if (Option == "novirt") {
7761 clearModuleFeatureBits(Mips::FeatureVirt, "virt");
7762
7763 // Synchronize the ABI Flags information with the FeatureBits information we
7764 // updated above.
7765 getTargetStreamer().updateABIInfo(*this);
7766
7767 // If printing assembly, use the recently updated ABI Flags information.
7768 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7769 // emitted later).
7770 getTargetStreamer().emitDirectiveModuleNoVirt();
7771
7772 // If this is not the end of the statement, report an error.
7773 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7774 reportParseError("unexpected token, expected end of statement");
7775 return false;
7776 }
7777
7778 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007779 } else if (Option == "ginv") {
7780 setModuleFeatureBits(Mips::FeatureGINV, "ginv");
7781
7782 // Synchronize the ABI Flags information with the FeatureBits information we
7783 // updated above.
7784 getTargetStreamer().updateABIInfo(*this);
7785
7786 // If printing assembly, use the recently updated ABI Flags information.
7787 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7788 // emitted later).
7789 getTargetStreamer().emitDirectiveModuleGINV();
7790
7791 // If this is not the end of the statement, report an error.
7792 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7793 reportParseError("unexpected token, expected end of statement");
7794 return false;
7795 }
7796
7797 return false; // parseDirectiveModule has finished successfully.
7798 } else if (Option == "noginv") {
7799 clearModuleFeatureBits(Mips::FeatureGINV, "ginv");
7800
7801 // Synchronize the ABI Flags information with the FeatureBits information we
7802 // updated above.
7803 getTargetStreamer().updateABIInfo(*this);
7804
7805 // If printing assembly, use the recently updated ABI Flags information.
7806 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7807 // emitted later).
7808 getTargetStreamer().emitDirectiveModuleNoGINV();
7809
7810 // If this is not the end of the statement, report an error.
7811 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7812 reportParseError("unexpected token, expected end of statement");
7813 return false;
7814 }
7815
7816 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007817 } else {
7818 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7819 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007820}
7821
7822/// parseDirectiveModuleFP
7823/// ::= =32
7824/// ::= =xx
7825/// ::= =64
7826bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007827 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007828 MCAsmLexer &Lexer = getLexer();
7829
7830 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007831 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007832 return false;
7833 }
7834 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007835
Daniel Sanders7e527422014-07-10 13:38:23 +00007836 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007837 if (!parseFpABIValue(FpABI, ".module"))
7838 return false;
7839
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007840 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007841 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007842 return false;
7843 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007844
Toma Tabacua64e5402015-06-25 12:44:38 +00007845 // Synchronize the abiflags information with the FeatureBits information we
7846 // changed above.
7847 getTargetStreamer().updateABIInfo(*this);
7848
7849 // If printing assembly, use the recently updated abiflags information.
7850 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7851 // emitted at the end).
7852 getTargetStreamer().emitDirectiveModuleFP();
7853
Daniel Sanders7e527422014-07-10 13:38:23 +00007854 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007855 return false;
7856}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007857
Daniel Sanders7e527422014-07-10 13:38:23 +00007858bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007859 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007860 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007861 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007862 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007863
7864 if (Lexer.is(AsmToken::Identifier)) {
7865 StringRef Value = Parser.getTok().getString();
7866 Parser.Lex();
7867
7868 if (Value != "xx") {
7869 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7870 return false;
7871 }
7872
7873 if (!isABI_O32()) {
7874 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7875 return false;
7876 }
7877
Daniel Sanders7e527422014-07-10 13:38:23 +00007878 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007879 if (ModuleLevelOptions) {
7880 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7881 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7882 } else {
7883 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7884 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7885 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007886 return true;
7887 }
7888
7889 if (Lexer.is(AsmToken::Integer)) {
7890 unsigned Value = Parser.getTok().getIntVal();
7891 Parser.Lex();
7892
7893 if (Value != 32 && Value != 64) {
7894 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7895 return false;
7896 }
7897
7898 if (Value == 32) {
7899 if (!isABI_O32()) {
7900 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7901 return false;
7902 }
7903
Daniel Sanders7e527422014-07-10 13:38:23 +00007904 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007905 if (ModuleLevelOptions) {
7906 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7907 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7908 } else {
7909 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7910 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7911 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007912 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007913 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007914 if (ModuleLevelOptions) {
7915 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7916 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7917 } else {
7918 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7919 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7920 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007921 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007922
Daniel Sanders7e527422014-07-10 13:38:23 +00007923 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007924 }
7925
7926 return false;
7927}
7928
Jack Carter0b744b32012-10-04 02:29:46 +00007929bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007930 // This returns false if this function recognizes the directive
7931 // regardless of whether it is successfully handles or reports an
7932 // error. Otherwise it returns true to give the generic parser a
7933 // chance at recognizing it.
7934
Rafael Espindola961d4692014-11-11 05:18:41 +00007935 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007936 StringRef IDVal = DirectiveID.getString();
7937
Nirav Dave996fc132016-05-05 14:15:46 +00007938 if (IDVal == ".cpload") {
7939 parseDirectiveCpLoad(DirectiveID.getLoc());
7940 return false;
7941 }
7942 if (IDVal == ".cprestore") {
7943 parseDirectiveCpRestore(DirectiveID.getLoc());
7944 return false;
7945 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007946 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007947 StringRef SymbolName;
7948
7949 if (Parser.parseIdentifier(SymbolName)) {
7950 reportParseError("expected identifier after .ent");
7951 return false;
7952 }
7953
7954 // There's an undocumented extension that allows an integer to
7955 // follow the name of the procedure which AFAICS is ignored by GAS.
7956 // Example: .ent foo,2
7957 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7958 if (getLexer().isNot(AsmToken::Comma)) {
7959 // Even though we accept this undocumented extension for compatibility
7960 // reasons, the additional integer argument does not actually change
7961 // the behaviour of the '.ent' directive, so we would like to discourage
7962 // its use. We do this by not referring to the extended version in
7963 // error messages which are not directly related to its use.
7964 reportParseError("unexpected token, expected end of statement");
7965 return false;
7966 }
7967 Parser.Lex(); // Eat the comma.
7968 const MCExpr *DummyNumber;
7969 int64_t DummyNumberVal;
7970 // If the user was explicitly trying to use the extended version,
7971 // we still give helpful extension-related error messages.
7972 if (Parser.parseExpression(DummyNumber)) {
7973 reportParseError("expected number after comma");
7974 return false;
7975 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007976 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007977 reportParseError("expected an absolute expression after comma");
7978 return false;
7979 }
7980 }
7981
7982 // If this is not the end of the statement, report an error.
7983 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7984 reportParseError("unexpected token, expected end of statement");
7985 return false;
7986 }
7987
Jim Grosbach6f482002015-05-18 18:43:14 +00007988 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007989
7990 getTargetStreamer().emitDirectiveEnt(*Sym);
7991 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007992 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007993 return false;
7994 }
7995
Jack Carter07c818d2013-01-25 01:31:34 +00007996 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007997 StringRef SymbolName;
7998
7999 if (Parser.parseIdentifier(SymbolName)) {
8000 reportParseError("expected identifier after .end");
8001 return false;
8002 }
8003
8004 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8005 reportParseError("unexpected token, expected end of statement");
8006 return false;
8007 }
8008
8009 if (CurrentFn == nullptr) {
8010 reportParseError(".end used without .ent");
8011 return false;
8012 }
8013
8014 if ((SymbolName != CurrentFn->getName())) {
8015 reportParseError(".end symbol does not match .ent symbol");
8016 return false;
8017 }
8018
8019 getTargetStreamer().emitDirectiveEnd(SymbolName);
8020 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00008021 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00008022 return false;
8023 }
8024
Jack Carter07c818d2013-01-25 01:31:34 +00008025 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008026 // .frame $stack_reg, frame_size_in_bytes, $return_reg
8027 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00008028 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00008029 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
8030 reportParseError("expected stack register");
8031 return false;
8032 }
8033
8034 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
8035 if (!StackRegOpnd.isGPRAsmReg()) {
8036 reportParseError(StackRegOpnd.getStartLoc(),
8037 "expected general purpose register");
8038 return false;
8039 }
8040 unsigned StackReg = StackRegOpnd.getGPR32Reg();
8041
8042 if (Parser.getTok().is(AsmToken::Comma))
8043 Parser.Lex();
8044 else {
8045 reportParseError("unexpected token, expected comma");
8046 return false;
8047 }
8048
8049 // Parse the frame size.
8050 const MCExpr *FrameSize;
8051 int64_t FrameSizeVal;
8052
8053 if (Parser.parseExpression(FrameSize)) {
8054 reportParseError("expected frame size value");
8055 return false;
8056 }
8057
Jim Grosbach13760bd2015-05-30 01:25:56 +00008058 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008059 reportParseError("frame size not an absolute expression");
8060 return false;
8061 }
8062
8063 if (Parser.getTok().is(AsmToken::Comma))
8064 Parser.Lex();
8065 else {
8066 reportParseError("unexpected token, expected comma");
8067 return false;
8068 }
8069
8070 // Parse the return register.
8071 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00008072 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00008073 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
8074 reportParseError("expected return register");
8075 return false;
8076 }
8077
8078 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
8079 if (!ReturnRegOpnd.isGPRAsmReg()) {
8080 reportParseError(ReturnRegOpnd.getStartLoc(),
8081 "expected general purpose register");
8082 return false;
8083 }
8084
8085 // If this is not the end of the statement, report an error.
8086 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8087 reportParseError("unexpected token, expected end of statement");
8088 return false;
8089 }
8090
8091 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
8092 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00008093 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00008094 return false;
8095 }
8096
Jack Carter07c818d2013-01-25 01:31:34 +00008097 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00008098 parseDirectiveSet();
8099 return false;
Jack Carterbe332172012-09-07 00:48:02 +00008100 }
8101
Daniel Sandersd97a6342014-08-13 10:07:34 +00008102 if (IDVal == ".mask" || IDVal == ".fmask") {
8103 // .mask bitmask, frame_offset
8104 // bitmask: One bit for each register used.
8105 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
8106 // first register is expected to be saved.
8107 // Examples:
8108 // .mask 0x80000000, -4
8109 // .fmask 0x80000000, -4
8110 //
Jack Carterbe332172012-09-07 00:48:02 +00008111
Daniel Sandersd97a6342014-08-13 10:07:34 +00008112 // Parse the bitmask
8113 const MCExpr *BitMask;
8114 int64_t BitMaskVal;
8115
8116 if (Parser.parseExpression(BitMask)) {
8117 reportParseError("expected bitmask value");
8118 return false;
8119 }
8120
Jim Grosbach13760bd2015-05-30 01:25:56 +00008121 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008122 reportParseError("bitmask not an absolute expression");
8123 return false;
8124 }
8125
8126 if (Parser.getTok().is(AsmToken::Comma))
8127 Parser.Lex();
8128 else {
8129 reportParseError("unexpected token, expected comma");
8130 return false;
8131 }
8132
8133 // Parse the frame_offset
8134 const MCExpr *FrameOffset;
8135 int64_t FrameOffsetVal;
8136
8137 if (Parser.parseExpression(FrameOffset)) {
8138 reportParseError("expected frame offset value");
8139 return false;
8140 }
8141
Jim Grosbach13760bd2015-05-30 01:25:56 +00008142 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008143 reportParseError("frame offset not an absolute expression");
8144 return false;
8145 }
8146
8147 // If this is not the end of the statement, report an error.
8148 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8149 reportParseError("unexpected token, expected end of statement");
8150 return false;
8151 }
8152
8153 if (IDVal == ".mask")
8154 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
8155 else
8156 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00008157 return false;
8158 }
8159
Matheus Almeida0051f2d2014-04-16 15:48:55 +00008160 if (IDVal == ".nan")
8161 return parseDirectiveNaN();
8162
Jack Carter07c818d2013-01-25 01:31:34 +00008163 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00008164 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00008165 return false;
8166 }
8167
Rafael Espindolab59fb732014-03-28 18:50:26 +00008168 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00008169 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00008170 return false;
8171 }
8172
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00008173 if (IDVal == ".dtprelword") {
8174 parseDirectiveDtpRelWord();
8175 return false;
8176 }
8177
8178 if (IDVal == ".dtpreldword") {
8179 parseDirectiveDtpRelDWord();
8180 return false;
8181 }
8182
8183 if (IDVal == ".tprelword") {
8184 parseDirectiveTpRelWord();
8185 return false;
8186 }
8187
8188 if (IDVal == ".tpreldword") {
8189 parseDirectiveTpRelDWord();
8190 return false;
8191 }
8192
Nirav Dave996fc132016-05-05 14:15:46 +00008193 if (IDVal == ".option") {
8194 parseDirectiveOption();
8195 return false;
8196 }
Jack Carter0cd3c192014-01-06 23:27:31 +00008197
8198 if (IDVal == ".abicalls") {
8199 getTargetStreamer().emitDirectiveAbiCalls();
8200 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Fangrui Songf78650a2018-07-30 19:41:25 +00008201 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00008202 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00008203 }
8204 return false;
8205 }
8206
Nirav Dave996fc132016-05-05 14:15:46 +00008207 if (IDVal == ".cpsetup") {
8208 parseDirectiveCPSetup();
8209 return false;
8210 }
8211 if (IDVal == ".cpreturn") {
8212 parseDirectiveCPReturn();
8213 return false;
8214 }
8215 if (IDVal == ".module") {
8216 parseDirectiveModule();
8217 return false;
8218 }
8219 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
8220 parseInternalDirectiveReallowModule();
8221 return false;
8222 }
8223 if (IDVal == ".insn") {
8224 parseInsnDirective();
8225 return false;
8226 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00008227 if (IDVal == ".rdata") {
8228 parseRSectionDirective(".rodata");
8229 return false;
8230 }
Nirav Dave996fc132016-05-05 14:15:46 +00008231 if (IDVal == ".sbss") {
8232 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
8233 return false;
8234 }
8235 if (IDVal == ".sdata") {
8236 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
8237 return false;
8238 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00008239
Rafael Espindola870c4e92012-01-11 03:56:41 +00008240 return true;
8241}
8242
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00008243bool MipsAsmParser::parseInternalDirectiveReallowModule() {
8244 // If this is not the end of the statement, report an error.
8245 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8246 reportParseError("unexpected token, expected end of statement");
8247 return false;
8248 }
8249
8250 getTargetStreamer().reallowModuleDirective();
8251
8252 getParser().Lex(); // Eat EndOfStatement token.
8253 return false;
8254}
8255
Rafael Espindola870c4e92012-01-11 03:56:41 +00008256extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00008257 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
8258 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
8259 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
8260 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00008261}
Jack Carterb4dbc172012-09-05 23:34:03 +00008262
8263#define GET_REGISTER_MATCHER
8264#define GET_MATCHER_IMPLEMENTATION
Simon Atanasyanc49da2e2018-09-13 08:38:03 +00008265#define GET_MNEMONIC_SPELL_CHECKER
Jack Carterb4dbc172012-09-05 23:34:03 +00008266#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00008267
8268bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
8269 // Find the appropriate table for this asm variant.
8270 const MatchEntry *Start, *End;
8271 switch (VariantID) {
8272 default: llvm_unreachable("invalid variant!");
8273 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
8274 }
8275 // Search the table.
8276 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
8277 return MnemonicRange.first != MnemonicRange.second;
8278}