blob: d2fed6861477b93964d091cbd8f6c6ccb408a018 [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"
Vladimir Stefanovic4433f932018-12-10 15:07:36 +000042#include "llvm/Support/CommandLine.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000043#include "llvm/Support/Compiler.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000044#include "llvm/Support/Debug.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000045#include "llvm/Support/ErrorHandling.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000046#include "llvm/Support/MathExtras.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000047#include "llvm/Support/SMLoc.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000048#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000049#include "llvm/Support/TargetRegistry.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000050#include "llvm/Support/raw_ostream.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000051#include <algorithm>
52#include <cassert>
53#include <cstdint>
Toma Tabacu9db22db2014-09-09 10:15:38 +000054#include <memory>
Eugene Zelenkodde94e42017-01-30 23:21:32 +000055#include <string>
56#include <utility>
Rafael Espindola870c4e92012-01-11 03:56:41 +000057
58using namespace llvm;
59
Chandler Carruthe96dd892014-04-21 22:55:11 +000060#define DEBUG_TYPE "mips-asm-parser"
61
Joey Gouly0e76fa72013-09-12 10:28:05 +000062namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000063
Joey Gouly0e76fa72013-09-12 10:28:05 +000064class MCInstrInfo;
Eugene Zelenkodde94e42017-01-30 23:21:32 +000065
66} // end namespace llvm
Joey Gouly0e76fa72013-09-12 10:28:05 +000067
Vladimir Stefanovic4433f932018-12-10 15:07:36 +000068static cl::opt<bool>
69EmitJalrReloc("mips-jalr-reloc", cl::Hidden,
70 cl::desc("MIPS: Emit R_{MICRO}MIPS_JALR relocation with jalr"),
71 cl::init(true));
72
Rafael Espindola870c4e92012-01-11 03:56:41 +000073namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000074
Jack Carter0b744b32012-10-04 02:29:46 +000075class MipsAssemblerOptions {
76public:
Eugene Zelenkodde94e42017-01-30 23:21:32 +000077 MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000078
Toma Tabacu9db22db2014-09-09 10:15:38 +000079 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000080 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000081 Reorder = Opts->isReorder();
82 Macro = Opts->isMacro();
83 Features = Opts->getFeatures();
84 }
85
Toma Tabacub19cf202015-04-27 13:12:59 +000086 unsigned getATRegIndex() const { return ATReg; }
87 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000088 if (Reg > 31)
89 return false;
90
91 ATReg = Reg;
92 return true;
93 }
Jack Carter0b744b32012-10-04 02:29:46 +000094
Toma Tabacu9db22db2014-09-09 10:15:38 +000095 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000096 void setReorder() { Reorder = true; }
97 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000098
Toma Tabacu9db22db2014-09-09 10:15:38 +000099 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +0000100 void setMacro() { Macro = true; }
101 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +0000102
Toma Tabacu465acfd2015-06-09 13:33:26 +0000103 const FeatureBitset &getFeatures() const { return Features; }
104 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000105
Daniel Sandersf0df2212014-08-04 12:20:00 +0000106 // Set of features that are either architecture features or referenced
107 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
108 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
109 // The reason we need this mask is explained in the selectArch function.
110 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000111 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +0000112
Jack Carter0b744b32012-10-04 02:29:46 +0000113private:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000114 unsigned ATReg = 1;
115 bool Reorder = true;
116 bool Macro = true;
Toma Tabacu465acfd2015-06-09 13:33:26 +0000117 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +0000118};
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000119
120} // end anonymous namespace
Jack Carter0b744b32012-10-04 02:29:46 +0000121
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000122const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
123 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
124 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
125 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
126 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
127 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
128 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
129 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
130 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
131};
132
Jack Carter0b744b32012-10-04 02:29:46 +0000133namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000134
Rafael Espindola870c4e92012-01-11 03:56:41 +0000135class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000136 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000137 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000138 return static_cast<MipsTargetStreamer &>(TS);
139 }
140
Eric Christophera5762812015-01-26 17:33:46 +0000141 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000142 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000143 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
144 // nullptr, which indicates that no function is currently
145 // selected. This usually happens after an '.end func'
146 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000147 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000148 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000149 bool IsCpRestoreSet;
150 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000151 unsigned CpSaveLocation;
152 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
153 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000154
Simon Atanasyan69301c92018-05-29 15:58:06 +0000155 // Map of register aliases created via the .set directive.
156 StringMap<AsmToken> RegisterSets;
157
Daniel Sandersef638fe2014-10-03 15:37:37 +0000158 // Print a warning along with its fix-it message at the given range.
159 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
160 SMRange Range, bool ShowColors = true);
161
Simon Dardis6a319922018-05-25 16:15:48 +0000162 void ConvertXWPOperands(MCInst &Inst, const OperandVector &Operands);
163
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000164#define GET_ASSEMBLER_HEADER
165#include "MipsGenAsmMatcher.inc"
166
Daniel Sandersc5537422016-07-27 13:49:44 +0000167 unsigned
168 checkEarlyTargetMatchPredicate(MCInst &Inst,
169 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000170 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
171
Chad Rosier49963552012-10-13 00:26:04 +0000172 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000173 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000174 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000175 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000176
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000177 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000178 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000179
Toma Tabacu13964452014-09-04 13:23:44 +0000180 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000181
Toma Tabacu13964452014-09-04 13:23:44 +0000182 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000183
Craig Topper55bc6cb2017-02-08 02:54:12 +0000184 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
185
David Blaikie960ea3f2014-06-08 16:18:35 +0000186 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
187 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000188
Craig Topper56c590a2014-04-29 07:58:02 +0000189 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000190
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000191 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
192 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000193 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000194 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000195 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
Simon Atanasyan69301c92018-05-29 15:58:06 +0000196 const AsmToken &Token,
197 SMLoc S);
198 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000199 SMLoc S);
200 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
201 OperandMatchResultTy parseImm(OperandVector &Operands);
202 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
203 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000204 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000205
David Blaikie960ea3f2014-06-08 16:18:35 +0000206 bool searchSymbolAlias(OperandVector &Operands);
207
Toma Tabacu13964452014-09-04 13:23:44 +0000208 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000209
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000210 enum MacroExpanderResultTy {
211 MER_NotAMacro,
212 MER_Success,
213 MER_Fail,
214 };
Jack Carter30a59822012-10-04 04:03:53 +0000215
Matheus Almeida3813d572014-06-19 14:39:14 +0000216 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000217 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
218 MCStreamer &Out,
219 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000220
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000221 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
222 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000223
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000224 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000225 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000226 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000227
Toma Tabacuf712ede2015-06-17 14:31:51 +0000228 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
229 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000230 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000231
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000232 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
233
Toma Tabacu00e98672015-05-01 12:19:27 +0000234 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000235 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000236
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000237 bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU,
238 SMLoc IDLoc, MCStreamer &Out,
239 const MCSubtargetInfo *STI);
240
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000241 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
242 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000243 SMLoc IDLoc, MCStreamer &Out,
244 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000245
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000246 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000248
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000249 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Simon Atanasyana1882672018-05-24 07:36:11 +0000250 const MCSubtargetInfo *STI, bool IsLoad);
Daniel Sandersfba875f2016-04-29 13:43:45 +0000251
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000252 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
253 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000254
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000255 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
256 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000257
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000258 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
259 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000260
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000261 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
262 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000263
Stefan Maksimovic0a239982018-07-09 13:06:44 +0000264 bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
265 const MCSubtargetInfo *STI, const bool IsMips64,
266 const bool Signed);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000267
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000268 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000269 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000270
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000271 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
272 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000273
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000274 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
275 const MCSubtargetInfo *STI);
276
277 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000278 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000279
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000280 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000281 MCStreamer &Out, const MCSubtargetInfo *STI);
282 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
283 const MCSubtargetInfo *STI);
284 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
285 const MCSubtargetInfo *STI);
286 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
287 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000288
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000289 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
290 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000291
Simon Dardis3c82a642017-02-08 16:25:05 +0000292 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
293 const MCSubtargetInfo *STI);
294
295 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
296 const MCSubtargetInfo *STI);
297
298 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
299 const MCSubtargetInfo *STI);
300
301 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
302 const MCSubtargetInfo *STI);
303
Simon Dardisaff4d142016-10-18 14:28:00 +0000304 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
305 const MCSubtargetInfo *STI, bool IsLoad);
306
Simon Dardis43115a12016-11-21 20:30:41 +0000307 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
308 const MCSubtargetInfo *STI);
309
310 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
311 const MCSubtargetInfo *STI);
312
Simon Dardisde5ed0c2017-11-14 22:26:42 +0000313 bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
314 const MCSubtargetInfo *STI);
315
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000316 bool reportParseError(Twine ErrorMsg);
317 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000318
Jack Carterb5cf5902013-04-17 00:18:04 +0000319 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000320
321 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000322 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000323 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000324 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000325 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000326 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000327 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000328 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000329 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000330 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000331 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000332 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000333 bool parseInsnDirective();
Simon Dardis1c73fcc2017-06-22 10:41:51 +0000334 bool parseRSectionDirective(StringRef Section);
Simon Atanasyanbe186202016-02-11 06:45:54 +0000335 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000336
337 bool parseSetAtDirective();
338 bool parseSetNoAtDirective();
339 bool parseSetMacroDirective();
340 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000341 bool parseSetMsaDirective();
342 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000343 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000344 bool parseSetReorderDirective();
345 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000346 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000347 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000348 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000349 bool parseSetOddSPRegDirective();
350 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000351 bool parseSetPopDirective();
352 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000353 bool parseSetSoftFloatDirective();
354 bool parseSetHardFloatDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +0000355 bool parseSetMtDirective();
356 bool parseSetNoMtDirective();
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000357 bool parseSetNoCRCDirective();
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000358 bool parseSetNoVirtDirective();
Petar Jovanovicdaf51692018-05-17 16:30:32 +0000359 bool parseSetNoGINVDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000360
Jack Carterd76b2372013-03-21 21:44:16 +0000361 bool parseSetAssignment();
362
Vladimir Medic4c299852013-11-06 11:27:05 +0000363 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000364 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000365 bool parseDirectiveDtpRelWord();
366 bool parseDirectiveDtpRelDWord();
367 bool parseDirectiveTpRelWord();
368 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000369 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000370 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000371 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
372 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000373
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000374 bool parseInternalDirectiveReallowModule();
375
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000376 bool eatComma(StringRef ErrorStr);
377
Jack Carter1ac53222013-02-20 23:11:17 +0000378 int matchCPURegisterName(StringRef Symbol);
379
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000380 int matchHWRegsRegisterName(StringRef Symbol);
381
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000382 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000383
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000384 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000385
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000386 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000387
Jack Carter5dc8ac92013-09-25 23:50:44 +0000388 int matchMSA128RegisterName(StringRef Name);
389
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000390 int matchMSA128CtrlRegisterName(StringRef Name);
391
Jack Carterd0bd6422013-04-18 00:41:53 +0000392 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000393
Toma Tabacu89a712b2015-04-15 10:48:56 +0000394 /// Returns the internal register number for the current AT. Also checks if
395 /// the current AT is unavailable (set to $0) and gives an error if it is.
396 /// This should be used in pseudo-instruction expansions which need AT.
397 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000398
Simon Dardis3aa8a902017-02-06 12:43:46 +0000399 bool canUseATReg();
400
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000401 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
402 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000403
404 // Helper function that checks if the value of a vector index is within the
405 // boundaries of accepted values for each RegisterKind
406 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
407 bool validateMSAIndex(int Val, int RegKind);
408
Daniel Sandersf0df2212014-08-04 12:20:00 +0000409 // Selects a new architecture by updating the FeatureBits with the necessary
410 // info including implied dependencies.
411 // Internally, it clears all the feature bits related to *any* architecture
412 // and selects the new one using the ToggleFeature functionality of the
413 // MCSubtargetInfo object that handles implied dependencies. The reason we
414 // clear all the arch related bits manually is because ToggleFeature only
415 // clears the features that imply the feature being cleared and not the
416 // features implied by the feature being cleared. This is easier to see
417 // with an example:
418 // --------------------------------------------------
419 // | Feature | Implies |
420 // | -------------------------------------------------|
421 // | FeatureMips1 | None |
422 // | FeatureMips2 | FeatureMips1 |
423 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
424 // | FeatureMips4 | FeatureMips3 |
425 // | ... | |
426 // --------------------------------------------------
427 //
428 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
429 // FeatureMipsGP64 | FeatureMips1)
430 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
431 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000432 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000433 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000434 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
435 STI.setFeatureBits(FeatureBits);
436 setAvailableFeatures(
437 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000438 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000439 }
440
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000441 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000442 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000443 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000444 setAvailableFeatures(
445 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000446 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000447 }
448 }
449
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000450 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000451 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000452 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000453 setAvailableFeatures(
454 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000455 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000456 }
457 }
458
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000459 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
460 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000461 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000462 }
463
464 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
465 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000466 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000467 }
468
Rafael Espindola870c4e92012-01-11 03:56:41 +0000469public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000470 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000471 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000472 Match_RequiresDifferentOperands,
473 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000474 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000475 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000476 Match_NonZeroOperandForSync,
Simon Dardis52ae4f02018-03-07 11:39:48 +0000477 Match_NonZeroOperandForMTCX,
Simon Dardis6f83ae32017-09-14 15:17:50 +0000478 Match_RequiresPosSizeRange0_32,
479 Match_RequiresPosSizeRange33_64,
Simon Dardis55e44672017-09-14 17:27:53 +0000480 Match_RequiresPosSizeUImm6,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000481#define GET_OPERAND_DIAGNOSTIC_TYPES
482#include "MipsGenAsmMatcher.inc"
483#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000484 };
485
Akira Hatanakab11ef082015-11-14 06:35:56 +0000486 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000487 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000488 : MCTargetAsmParser(Options, sti, MII),
Daniel Sanders50f17232015-09-15 16:17:27 +0000489 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
490 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000491 MCAsmParserExtension::Initialize(parser);
492
Toma Tabacu11e14a92015-04-21 11:50:52 +0000493 parser.addAliasForDirective(".asciiz", ".asciz");
Simon Atanasyanb5244592018-07-25 07:07:43 +0000494 parser.addAliasForDirective(".hword", ".2byte");
495 parser.addAliasForDirective(".word", ".4byte");
496 parser.addAliasForDirective(".dword", ".8byte");
Toma Tabacu11e14a92015-04-21 11:50:52 +0000497
Jack Carterb4dbc172012-09-05 23:34:03 +0000498 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000500
Toma Tabacu9db22db2014-09-09 10:15:38 +0000501 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000502 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000503 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000504
Toma Tabacu9db22db2014-09-09 10:15:38 +0000505 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000506 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000507 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000508
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000509 getTargetStreamer().updateABIInfo(*this);
510
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000511 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000512 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000513
514 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000515
Rafael Espindola699281c2016-05-18 11:58:50 +0000516 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000517
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000518 IsCpRestoreSet = false;
519 CpRestoreOffset = -1;
520
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000521 const Triple &TheTriple = sti.getTargetTriple();
Alexander Richardson85e200e2018-06-25 16:49:20 +0000522 IsLittleEndian = TheTriple.isLittleEndian();
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +0000523
524 if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
525 report_fatal_error("microMIPS64R6 is not supported", false);
Simon Dardisaf38a8f2018-06-19 16:05:44 +0000526
527 if (!isABI_O32() && inMicroMipsMode())
528 report_fatal_error("microMIPS64 is not supported", false);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000529 }
530
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000531 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
532 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
533
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000534 bool isGP64bit() const {
535 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
536 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000537
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000538 bool isFP64bit() const {
539 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
540 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000541
Eric Christophera5762812015-01-26 17:33:46 +0000542 const MipsABIInfo &getABI() const { return ABI; }
543 bool isABI_N32() const { return ABI.IsN32(); }
544 bool isABI_N64() const { return ABI.IsN64(); }
545 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000546 bool isABI_FPXX() const {
547 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
548 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000549
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000550 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000551 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000552 }
553
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000554 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000555 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000556 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000557
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000558 bool hasMips1() const {
559 return getSTI().getFeatureBits()[Mips::FeatureMips1];
560 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000561
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000562 bool hasMips2() const {
563 return getSTI().getFeatureBits()[Mips::FeatureMips2];
564 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000565
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000566 bool hasMips3() const {
567 return getSTI().getFeatureBits()[Mips::FeatureMips3];
568 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000569
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000570 bool hasMips4() const {
571 return getSTI().getFeatureBits()[Mips::FeatureMips4];
572 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000573
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000574 bool hasMips5() const {
575 return getSTI().getFeatureBits()[Mips::FeatureMips5];
576 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000577
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000578 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000579 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000580 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000581
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000582 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000583 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000584 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000585
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000586 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000587 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000588 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000589
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000590 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000591 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000592 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000593
Daniel Sanders17793142015-02-18 16:24:50 +0000594 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000595 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000596 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000597
Daniel Sanders17793142015-02-18 16:24:50 +0000598 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000599 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000600 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000601
Daniel Sanders17793142015-02-18 16:24:50 +0000602 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000603 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000604 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000605
Daniel Sanders17793142015-02-18 16:24:50 +0000606 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000607 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000608 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000609
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000610 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000611 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000612 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000613
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000614 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000615 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000616 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000617
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000618 bool hasDSP() const {
619 return getSTI().getFeatureBits()[Mips::FeatureDSP];
620 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000621
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000622 bool hasDSPR2() const {
623 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
624 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000625
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000626 bool hasDSPR3() const {
627 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
628 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000629
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000630 bool hasMSA() const {
631 return getSTI().getFeatureBits()[Mips::FeatureMSA];
632 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000633
Kai Nackee0245392015-01-27 19:11:28 +0000634 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000635 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000636 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000637
Daniel Sandersa6994442015-08-18 12:33:54 +0000638 bool inPicMode() {
639 return IsPicEnabled;
640 }
641
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000642 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000643 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000644 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000645
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000646 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000647 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000648 }
649
Eric Christophere8ae3e32015-05-07 23:10:21 +0000650 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000651 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000652 }
Simon Dardisae719c52017-07-11 18:03:20 +0000653 bool hasMT() const {
654 return getSTI().getFeatureBits()[Mips::FeatureMT];
655 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000656
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000657 bool hasCRC() const {
658 return getSTI().getFeatureBits()[Mips::FeatureCRC];
659 }
660
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000661 bool hasVirt() const {
662 return getSTI().getFeatureBits()[Mips::FeatureVirt];
663 }
664
Petar Jovanovicdaf51692018-05-17 16:30:32 +0000665 bool hasGINV() const {
666 return getSTI().getFeatureBits()[Mips::FeatureGINV];
667 }
668
Toma Tabacud9d344b2015-04-27 14:05:04 +0000669 /// Warn if RegIndex is the same as the current AT.
670 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000671
672 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000673
674 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000675
676 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
677 AsmToken::TokenKind OperatorToken,
678 MCContext &Ctx) override {
679 switch(OperatorToken) {
680 default:
681 llvm_unreachable("Unknown token");
682 return nullptr;
683 case AsmToken::PercentCall16:
684 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
685 case AsmToken::PercentCall_Hi:
686 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
687 case AsmToken::PercentCall_Lo:
688 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
689 case AsmToken::PercentDtprel_Hi:
690 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
691 case AsmToken::PercentDtprel_Lo:
692 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
693 case AsmToken::PercentGot:
694 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
695 case AsmToken::PercentGot_Disp:
696 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
697 case AsmToken::PercentGot_Hi:
698 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
699 case AsmToken::PercentGot_Lo:
700 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
701 case AsmToken::PercentGot_Ofst:
702 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
703 case AsmToken::PercentGot_Page:
704 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
705 case AsmToken::PercentGottprel:
706 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
707 case AsmToken::PercentGp_Rel:
708 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
709 case AsmToken::PercentHi:
710 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
711 case AsmToken::PercentHigher:
712 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
713 case AsmToken::PercentHighest:
714 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
715 case AsmToken::PercentLo:
716 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
717 case AsmToken::PercentNeg:
718 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
719 case AsmToken::PercentPcrel_Hi:
720 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
721 case AsmToken::PercentPcrel_Lo:
722 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
723 case AsmToken::PercentTlsgd:
724 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
725 case AsmToken::PercentTlsldm:
726 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
727 case AsmToken::PercentTprel_Hi:
728 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
729 case AsmToken::PercentTprel_Lo:
730 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
731 }
732 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000733};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000734
735/// MipsOperand - Instances of this class represent a parsed Mips machine
736/// instruction.
737class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000738public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000739 /// Broad categories of register classes
740 /// The exact class is finalized by the render method.
741 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000742 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000743 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000744 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000745 RegKind_FCC = 4, /// FCC
746 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
747 RegKind_MSACtrl = 16, /// MSA control registers
748 RegKind_COP2 = 32, /// COP2
749 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
750 /// context).
751 RegKind_CCR = 128, /// CCR
752 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000753 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000754 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000755 /// Potentially any (e.g. $1)
756 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
757 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000758 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000759 };
760
761private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000762 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000763 k_Immediate, /// An immediate (possibly involving symbol references)
764 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000765 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000766 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000767 k_RegList, /// A physical register list
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000768 } Kind;
769
David Blaikie960ea3f2014-06-08 16:18:35 +0000770public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000771 MipsOperand(KindTy K, MipsAsmParser &Parser)
772 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
773
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000774 ~MipsOperand() override {
775 switch (Kind) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000776 case k_Memory:
777 delete Mem.Base;
778 break;
779 case k_RegList:
780 delete RegList.List;
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000781 break;
782 case k_Immediate:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000783 case k_RegisterIndex:
784 case k_Token:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000785 break;
786 }
787 }
788
David Blaikie960ea3f2014-06-08 16:18:35 +0000789private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000790 /// For diagnostics, and checking the assembler temporary
791 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000792
Eric Christopher8996c5d2013-03-15 00:42:55 +0000793 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000794 const char *Data;
795 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000796 };
797
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000798 struct RegIdxOp {
799 unsigned Index; /// Index into the register class
800 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000801 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000802 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000803 };
804
805 struct ImmOp {
806 const MCExpr *Val;
807 };
808
809 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000810 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000811 const MCExpr *Off;
812 };
813
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000814 struct RegListOp {
815 SmallVector<unsigned, 10> *List;
816 };
817
Jack Carterb4dbc172012-09-05 23:34:03 +0000818 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000819 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000820 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000821 struct ImmOp Imm;
822 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000823 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000824 };
825
826 SMLoc StartLoc, EndLoc;
827
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000828 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000829 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
830 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000831 const MCRegisterInfo *RegInfo,
832 SMLoc S, SMLoc E,
833 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000834 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000835 Op->RegIdx.Index = Index;
836 Op->RegIdx.RegInfo = RegInfo;
837 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000838 Op->RegIdx.Tok.Data = Str.data();
839 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000840 Op->StartLoc = S;
841 Op->EndLoc = E;
842 return Op;
843 }
844
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000845public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000846 /// Coerce the register to GPR32 and return the real register for the current
847 /// target.
848 unsigned getGPR32Reg() const {
849 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000850 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000851 unsigned ClassID = Mips::GPR32RegClassID;
852 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000853 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000854
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000855 /// Coerce the register to GPR32 and return the real register for the current
856 /// target.
857 unsigned getGPRMM16Reg() const {
858 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
859 unsigned ClassID = Mips::GPR32RegClassID;
860 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
861 }
862
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000863 /// Coerce the register to GPR64 and return the real register for the current
864 /// target.
865 unsigned getGPR64Reg() const {
866 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
867 unsigned ClassID = Mips::GPR64RegClassID;
868 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000869 }
870
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000871private:
872 /// Coerce the register to AFGR64 and return the real register for the current
873 /// target.
874 unsigned getAFGR64Reg() const {
875 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
876 if (RegIdx.Index % 2 != 0)
877 AsmParser.Warning(StartLoc, "Float register should be even.");
878 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
879 .getRegister(RegIdx.Index / 2);
880 }
881
882 /// Coerce the register to FGR64 and return the real register for the current
883 /// target.
884 unsigned getFGR64Reg() const {
885 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
886 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
887 .getRegister(RegIdx.Index);
888 }
889
890 /// Coerce the register to FGR32 and return the real register for the current
891 /// target.
892 unsigned getFGR32Reg() const {
893 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
894 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
895 .getRegister(RegIdx.Index);
896 }
897
898 /// Coerce the register to FGRH32 and return the real register for the current
899 /// target.
900 unsigned getFGRH32Reg() const {
901 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
902 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
903 .getRegister(RegIdx.Index);
904 }
905
906 /// Coerce the register to FCC and return the real register for the current
907 /// target.
908 unsigned getFCCReg() const {
909 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
910 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
911 .getRegister(RegIdx.Index);
912 }
913
914 /// Coerce the register to MSA128 and return the real register for the current
915 /// target.
916 unsigned getMSA128Reg() const {
917 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
918 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
919 // identical
920 unsigned ClassID = Mips::MSA128BRegClassID;
921 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
922 }
923
924 /// Coerce the register to MSACtrl and return the real register for the
925 /// current target.
926 unsigned getMSACtrlReg() const {
927 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
928 unsigned ClassID = Mips::MSACtrlRegClassID;
929 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
930 }
931
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000932 /// Coerce the register to COP0 and return the real register for the
933 /// current target.
934 unsigned getCOP0Reg() const {
935 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
936 unsigned ClassID = Mips::COP0RegClassID;
937 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
938 }
939
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000940 /// Coerce the register to COP2 and return the real register for the
941 /// current target.
942 unsigned getCOP2Reg() const {
943 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
944 unsigned ClassID = Mips::COP2RegClassID;
945 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
946 }
947
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000948 /// Coerce the register to COP3 and return the real register for the
949 /// current target.
950 unsigned getCOP3Reg() const {
951 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
952 unsigned ClassID = Mips::COP3RegClassID;
953 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
954 }
955
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000956 /// Coerce the register to ACC64DSP and return the real register for the
957 /// current target.
958 unsigned getACC64DSPReg() const {
959 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
960 unsigned ClassID = Mips::ACC64DSPRegClassID;
961 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
962 }
963
964 /// Coerce the register to HI32DSP and return the real register for the
965 /// current target.
966 unsigned getHI32DSPReg() const {
967 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
968 unsigned ClassID = Mips::HI32DSPRegClassID;
969 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
970 }
971
972 /// Coerce the register to LO32DSP and return the real register for the
973 /// current target.
974 unsigned getLO32DSPReg() const {
975 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
976 unsigned ClassID = Mips::LO32DSPRegClassID;
977 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
978 }
979
980 /// Coerce the register to CCR and return the real register for the
981 /// current target.
982 unsigned getCCRReg() const {
983 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
984 unsigned ClassID = Mips::CCRRegClassID;
985 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
986 }
987
988 /// Coerce the register to HWRegs and return the real register for the
989 /// current target.
990 unsigned getHWRegsReg() const {
991 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
992 unsigned ClassID = Mips::HWRegsRegClassID;
993 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
994 }
995
996public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000997 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000998 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000999 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001000 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +00001001 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001002 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +00001003 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001004 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001005 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001006
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001007 void addRegOperands(MCInst &Inst, unsigned N) const {
1008 llvm_unreachable("Use a custom parser instead");
1009 }
1010
Daniel Sanders21bce302014-04-01 12:35:23 +00001011 /// Render the operand to an MCInst as a GPR32
1012 /// Asserts if the wrong number of operands are requested, or the operand
1013 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +00001014 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1015 assert(N == 1 && "Invalid number of operands!");
1016 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1017 }
1018
1019 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1020 assert(N == 1 && "Invalid number of operands!");
1021 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1022 }
1023
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001024 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1025 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001026 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001027 }
1028
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001029 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
1030 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001031 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001032 }
1033
Jozef Kolek1904fa22014-11-24 14:25:53 +00001034 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1035 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001036 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001037 }
1038
Zoran Jovanovic41688672015-02-10 16:36:20 +00001039 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1040 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001041 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001042 }
1043
Simon Atanasyan852dd832018-09-19 18:46:21 +00001044 void addGPRMM16AsmRegMovePPairFirstOperands(MCInst &Inst, unsigned N) const {
1045 assert(N == 1 && "Invalid number of operands!");
1046 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
1047 }
1048
1049 void addGPRMM16AsmRegMovePPairSecondOperands(MCInst &Inst,
1050 unsigned N) const {
1051 assert(N == 1 && "Invalid number of operands!");
1052 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
1053 }
1054
Daniel Sanders21bce302014-04-01 12:35:23 +00001055 /// Render the operand to an MCInst as a GPR64
1056 /// Asserts if the wrong number of operands are requested, or the operand
1057 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001058 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1059 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001060 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001061 }
1062
1063 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1064 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001065 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001066 }
1067
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001068 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1069 assert(N == 1 && "Invalid number of operands!");
1070 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1071 }
1072
1073 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1074 assert(N == 1 && "Invalid number of operands!");
1075 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1076 }
1077
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001078 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1079 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001080 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001081 }
1082
1083 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1084 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001085 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001086 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001087 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001088 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001089 AsmParser.getParser().printError(
1090 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1091 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001092 }
1093
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001094 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1095 assert(N == 1 && "Invalid number of operands!");
1096 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1097 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1098 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1099 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1100 "registers");
1101 }
1102
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001103 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1104 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001105 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001106 }
1107
1108 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1109 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001110 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001111 }
1112
1113 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1114 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001115 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001116 }
1117
1118 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1119 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001120 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001121 }
1122
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001123 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1124 assert(N == 1 && "Invalid number of operands!");
1125 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1126 }
1127
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001128 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1129 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001130 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001131 }
1132
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001133 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1134 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001135 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001136 }
1137
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001138 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1139 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001140 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001141 }
1142
1143 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1144 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001145 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001146 }
1147
1148 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1149 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001150 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001151 }
1152
1153 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1154 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001155 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001156 }
1157
1158 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1159 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001160 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001161 }
1162
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001163 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001164 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1165 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001166 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001167 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001168 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001169 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001170 Inst.addOperand(MCOperand::createImm(Imm));
1171 }
1172
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001173 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001174 void addSImmOperands(MCInst &Inst, unsigned N) const {
1175 if (isImm() && !isConstantImm()) {
1176 addExpr(Inst, getImm());
1177 return;
1178 }
1179 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1180 }
1181
1182 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001183 void addUImmOperands(MCInst &Inst, unsigned N) const {
1184 if (isImm() && !isConstantImm()) {
1185 addExpr(Inst, getImm());
1186 return;
1187 }
1188 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1189 }
1190
Daniel Sanders78e89022016-03-11 11:37:50 +00001191 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1192 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1193 assert(N == 1 && "Invalid number of operands!");
1194 int64_t Imm = getConstantImm() - Offset;
1195 Imm = SignExtend64<Bits>(Imm);
1196 Imm += Offset;
1197 Imm += AdjustOffset;
1198 Inst.addOperand(MCOperand::createImm(Imm));
1199 }
1200
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001201 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001202 assert(N == 1 && "Invalid number of operands!");
1203 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001204 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001205 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001206
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001207 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001208 assert(N == 2 && "Invalid number of operands!");
1209
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001210 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1211 ? getMemBase()->getGPR64Reg()
1212 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001213
1214 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001215 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001216 }
1217
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001218 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1219 assert(N == 2 && "Invalid number of operands!");
1220
Jim Grosbache9119e42015-05-13 18:37:00 +00001221 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001222
1223 const MCExpr *Expr = getMemOff();
1224 addExpr(Inst, Expr);
1225 }
1226
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001227 void addRegListOperands(MCInst &Inst, unsigned N) const {
1228 assert(N == 1 && "Invalid number of operands!");
1229
1230 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001231 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001232 }
1233
Craig Topper56c590a2014-04-29 07:58:02 +00001234 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001235 // As a special case until we sort out the definition of div/divu, accept
1236 // $0/$zero here so that MCK_ZERO works correctly.
1237 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001238 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001239
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001240 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001241 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001242
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001243 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001244 int64_t Res;
1245 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001246 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001247
Daniel Sanders52da7af2015-11-06 12:11:03 +00001248 bool isConstantImmz() const {
1249 return isConstantImm() && getConstantImm() == 0;
1250 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001251
Daniel Sandersea4f6532015-11-06 12:22:31 +00001252 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1253 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1254 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001255
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001256 template <unsigned Bits> bool isSImm() const {
1257 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1258 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001259
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001260 template <unsigned Bits> bool isUImm() const {
1261 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1262 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001263
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001264 template <unsigned Bits> bool isAnyImm() const {
1265 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1266 isUInt<Bits>(getConstantImm()))
1267 : isImm();
1268 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001269
Daniel Sanders78e89022016-03-11 11:37:50 +00001270 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1271 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001272 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001273
Hrvoje Varga46458d02016-02-25 12:53:29 +00001274 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1275 return isConstantImm() && getConstantImm() >= Bottom &&
1276 getConstantImm() <= Top;
1277 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001278
Craig Topper56c590a2014-04-29 07:58:02 +00001279 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001280 // Note: It's not possible to pretend that other operand kinds are tokens.
1281 // The matcher emitter checks tokens first.
1282 return Kind == k_Token;
1283 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001284
Craig Topper56c590a2014-04-29 07:58:02 +00001285 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001286
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001287 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001288 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001289 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001290
Simon Dardis4ccda502016-05-27 13:56:36 +00001291 // Allow relocation operators.
1292 // FIXME: This predicate and others need to look through binary expressions
1293 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001294 template <unsigned Bits, unsigned ShiftAmount = 0>
1295 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001296 if (!isMem())
1297 return false;
1298 if (!getMemBase()->isGPRAsmReg())
1299 return false;
1300 if (isa<MCTargetExpr>(getMemOff()) ||
1301 (isConstantMemOff() &&
1302 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1303 return true;
1304 MCValue Res;
1305 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1306 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001307 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001308
Simon Atanasyand4d892f2018-04-26 19:55:28 +00001309 bool isMemWithPtrSizeOffset() const {
1310 if (!isMem())
1311 return false;
1312 if (!getMemBase()->isGPRAsmReg())
1313 return false;
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00001314 const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32;
Simon Atanasyand4d892f2018-04-26 19:55:28 +00001315 if (isa<MCTargetExpr>(getMemOff()) ||
1316 (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))
1317 return true;
1318 MCValue Res;
1319 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1320 return IsReloc && isIntN(PtrBits, Res.getConstant());
1321 }
1322
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001323 bool isMemWithGRPMM16Base() const {
1324 return isMem() && getMemBase()->isMM16AsmReg();
1325 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001326
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001327 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1328 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1329 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1330 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001331
Jozef Kolek12c69822014-12-23 16:16:33 +00001332 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1333 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1334 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1335 && (getMemBase()->getGPR32Reg() == Mips::SP);
1336 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001337
Daniel Sanderse473dc92016-05-09 13:38:25 +00001338 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1339 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1340 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1341 && (getMemBase()->getGPR32Reg() == Mips::GP);
1342 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001343
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001344 template <unsigned Bits, unsigned ShiftLeftAmount>
1345 bool isScaledUImm() const {
1346 return isConstantImm() &&
1347 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001348 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001349
Daniel Sanders97297772016-03-22 14:40:00 +00001350 template <unsigned Bits, unsigned ShiftLeftAmount>
1351 bool isScaledSImm() const {
Simon Atanasyan478220f2018-05-24 07:36:00 +00001352 if (isConstantImm() &&
1353 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001354 return true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00001355 // Operand can also be a symbol or symbol plus
1356 // offset in case of relocations.
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001357 if (Kind != k_Immediate)
1358 return false;
1359 MCValue Res;
1360 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1361 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001362 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001363
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001364 bool isRegList16() const {
1365 if (!isRegList())
1366 return false;
1367
1368 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001369 if (Size < 2 || Size > 5)
1370 return false;
1371
1372 unsigned R0 = RegList.List->front();
1373 unsigned R1 = RegList.List->back();
1374 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1375 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001376 return false;
1377
1378 int PrevReg = *RegList.List->begin();
1379 for (int i = 1; i < Size - 1; i++) {
1380 int Reg = (*(RegList.List))[i];
1381 if ( Reg != PrevReg + 1)
1382 return false;
1383 PrevReg = Reg;
1384 }
1385
1386 return true;
1387 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001388
Vladimir Medic2b953d02013-10-01 09:48:56 +00001389 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001390
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001391 bool isLSAImm() const {
1392 if (!isConstantImm())
1393 return false;
1394 int64_t Val = getConstantImm();
1395 return 1 <= Val && Val <= 4;
1396 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001397
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001398 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001399
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001400 StringRef getToken() const {
1401 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001402 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001403 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001404
Craig Topper56c590a2014-04-29 07:58:02 +00001405 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001406 // As a special case until we sort out the definition of div/divu, accept
1407 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001408 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1409 RegIdx.Kind & RegKind_GPR)
1410 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001411
Daniel Sanders976d9382016-07-05 13:38:40 +00001412 llvm_unreachable("Invalid access!");
1413 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001414 }
1415
Jack Carterb4dbc172012-09-05 23:34:03 +00001416 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001417 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001418 return Imm.Val;
1419 }
1420
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001421 int64_t getConstantImm() const {
1422 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001423 int64_t Value = 0;
1424 (void)Val->evaluateAsAbsolute(Value);
1425 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001426 }
1427
1428 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001429 assert((Kind == k_Memory) && "Invalid access!");
1430 return Mem.Base;
1431 }
1432
1433 const MCExpr *getMemOff() const {
1434 assert((Kind == k_Memory) && "Invalid access!");
1435 return Mem.Off;
1436 }
1437
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001438 int64_t getConstantMemOff() const {
1439 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1440 }
1441
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001442 const SmallVectorImpl<unsigned> &getRegList() const {
1443 assert((Kind == k_RegList) && "Invalid access!");
1444 return *(RegList.List);
1445 }
1446
David Blaikie960ea3f2014-06-08 16:18:35 +00001447 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1448 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001449 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001450 Op->Tok.Data = Str.data();
1451 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001452 Op->StartLoc = S;
1453 Op->EndLoc = S;
1454 return Op;
1455 }
1456
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001457 /// Create a numeric register (e.g. $1). The exact register remains
1458 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001459 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001460 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1461 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001462 LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001463 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001464 }
1465
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001466 /// Create a register that is definitely a GPR.
1467 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001468 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001469 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1470 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1471 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001472 }
1473
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001474 /// Create a register that is definitely a FGR.
1475 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001476 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001477 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1478 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1479 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001480 }
1481
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001482 /// Create a register that is definitely a HWReg.
1483 /// This is typically only used for named registers such as $hwr_cpunum.
1484 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001485 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001486 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001487 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001488 }
1489
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001490 /// Create a register that is definitely an FCC.
1491 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001492 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001493 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1494 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1495 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001496 }
1497
1498 /// Create a register that is definitely an ACC.
1499 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001500 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001501 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1502 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1503 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001504 }
1505
1506 /// Create a register that is definitely an MSA128.
1507 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001508 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001509 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1510 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1511 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001512 }
1513
1514 /// Create a register that is definitely an MSACtrl.
1515 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001516 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001517 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1518 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1519 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001520 }
1521
David Blaikie960ea3f2014-06-08 16:18:35 +00001522 static std::unique_ptr<MipsOperand>
1523 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001524 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001525 Op->Imm.Val = Val;
1526 Op->StartLoc = S;
1527 Op->EndLoc = E;
1528 return Op;
1529 }
1530
David Blaikie960ea3f2014-06-08 16:18:35 +00001531 static std::unique_ptr<MipsOperand>
1532 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1533 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001534 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001535 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001536 Op->Mem.Off = Off;
1537 Op->StartLoc = S;
1538 Op->EndLoc = E;
1539 return Op;
1540 }
1541
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001542 static std::unique_ptr<MipsOperand>
1543 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1544 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001545 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001546
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001547 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001548 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001549 Op->StartLoc = StartLoc;
1550 Op->EndLoc = EndLoc;
1551 return Op;
1552 }
1553
Simon Dardis509da1a2017-02-13 16:06:48 +00001554 bool isGPRZeroAsmReg() const {
1555 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1556 }
1557
1558 bool isGPRNonZeroAsmReg() const {
1559 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1560 RegIdx.Index <= 31;
1561 }
1562
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001563 bool isGPRAsmReg() const {
1564 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001565 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001566
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001567 bool isMM16AsmReg() const {
1568 if (!(isRegIdx() && RegIdx.Kind))
1569 return false;
1570 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1571 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001572
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001573 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001574 bool isMM16AsmRegZero() const {
1575 if (!(isRegIdx() && RegIdx.Kind))
1576 return false;
1577 return (RegIdx.Index == 0 ||
1578 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1579 RegIdx.Index == 17);
1580 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001581
Zoran Jovanovic41688672015-02-10 16:36:20 +00001582 bool isMM16AsmRegMoveP() const {
1583 if (!(isRegIdx() && RegIdx.Kind))
1584 return false;
1585 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1586 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1587 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001588
Simon Atanasyan852dd832018-09-19 18:46:21 +00001589 bool isMM16AsmRegMovePPairFirst() const {
1590 if (!(isRegIdx() && RegIdx.Kind))
1591 return false;
1592 return RegIdx.Index >= 4 && RegIdx.Index <= 6;
1593 }
1594
1595 bool isMM16AsmRegMovePPairSecond() const {
1596 if (!(isRegIdx() && RegIdx.Kind))
1597 return false;
1598 return (RegIdx.Index == 21 || RegIdx.Index == 22 ||
1599 (RegIdx.Index >= 5 && RegIdx.Index <= 7));
1600 }
1601
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001602 bool isFGRAsmReg() const {
1603 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1604 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001605 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001606
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001607 bool isStrictlyFGRAsmReg() const {
1608 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1609 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1610 }
1611
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001612 bool isHWRegsAsmReg() const {
1613 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001614 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001615
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001616 bool isCCRAsmReg() const {
1617 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001618 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001619
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001620 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001621 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1622 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001623 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001624 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001625
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001626 bool isACCAsmReg() const {
1627 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001628 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001629
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001630 bool isCOP0AsmReg() const {
1631 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1632 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001633
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001634 bool isCOP2AsmReg() const {
1635 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001636 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001637
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001638 bool isCOP3AsmReg() const {
1639 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1640 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001641
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001642 bool isMSA128AsmReg() const {
1643 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001644 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001645
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001646 bool isMSACtrlAsmReg() const {
1647 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001648 }
1649
Jack Carterb4dbc172012-09-05 23:34:03 +00001650 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001651 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001652 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001653 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001654
Craig Topper56c590a2014-04-29 07:58:02 +00001655 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001656 switch (Kind) {
1657 case k_Immediate:
1658 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001659 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001660 OS << ">";
1661 break;
1662 case k_Memory:
1663 OS << "Mem<";
1664 Mem.Base->print(OS);
1665 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001666 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001667 OS << ">";
1668 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001669 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001670 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1671 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001672 break;
1673 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001674 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001675 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001676 case k_RegList:
1677 OS << "RegList< ";
1678 for (auto Reg : (*RegList.List))
1679 OS << Reg << " ";
1680 OS << ">";
1681 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001682 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001683 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001684
1685 bool isValidForTie(const MipsOperand &Other) const {
1686 if (Kind != Other.Kind)
1687 return false;
1688
1689 switch (Kind) {
1690 default:
1691 llvm_unreachable("Unexpected kind");
1692 return false;
1693 case k_RegisterIndex: {
1694 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1695 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1696 return Token == OtherToken;
1697 }
1698 }
1699 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001700}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001701
1702} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001703
Jack Carter9e65aa32013-03-22 00:05:30 +00001704namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001705
Jack Carter9e65aa32013-03-22 00:05:30 +00001706extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001707
1708} // end namespace llvm
1709
Jack Carter9e65aa32013-03-22 00:05:30 +00001710static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1711 return MipsInsts[Opcode];
1712}
1713
Aleksandar Beserminji8abf6802019-01-09 15:58:02 +00001714static bool hasShortDelaySlot(MCInst &Inst) {
1715 switch (Inst.getOpcode()) {
1716 case Mips::BEQ_MM:
1717 case Mips::BNE_MM:
1718 case Mips::BLTZ_MM:
1719 case Mips::BGEZ_MM:
1720 case Mips::BLEZ_MM:
1721 case Mips::BGTZ_MM:
1722 case Mips::JRC16_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001723 case Mips::JALS_MM:
1724 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001725 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001726 case Mips::BGEZALS_MM:
1727 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001728 return true;
Aleksandar Beserminji8abf6802019-01-09 15:58:02 +00001729 case Mips::J_MM:
1730 return !Inst.getOperand(0).isReg();
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001731 default:
1732 return false;
1733 }
1734}
1735
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001736static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1737 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1738 return &SRExpr->getSymbol();
1739 }
1740
1741 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1742 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1743 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1744
1745 if (LHSSym)
1746 return LHSSym;
1747
1748 if (RHSSym)
1749 return RHSSym;
1750
1751 return nullptr;
1752 }
1753
1754 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1755 return getSingleMCSymbol(UExpr->getSubExpr());
1756
1757 return nullptr;
1758}
1759
1760static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1761 if (isa<MCSymbolRefExpr>(Expr))
1762 return 1;
1763
1764 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1765 return countMCSymbolRefExpr(BExpr->getLHS()) +
1766 countMCSymbolRefExpr(BExpr->getRHS());
1767
1768 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1769 return countMCSymbolRefExpr(UExpr->getSubExpr());
1770
1771 return 0;
1772}
1773
Jack Carter9e65aa32013-03-22 00:05:30 +00001774bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001775 MCStreamer &Out,
1776 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001777 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001778 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001779 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001780
Jack Carter9e65aa32013-03-22 00:05:30 +00001781 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001782
1783 if (MCID.isBranch() || MCID.isCall()) {
1784 const unsigned Opcode = Inst.getOpcode();
1785 MCOperand Offset;
1786
1787 switch (Opcode) {
1788 default:
1789 break;
Kai Nackee0245392015-01-27 19:11:28 +00001790 case Mips::BBIT0:
1791 case Mips::BBIT032:
1792 case Mips::BBIT1:
1793 case Mips::BBIT132:
1794 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001795 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001796
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001797 case Mips::BEQ:
1798 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001799 case Mips::BEQ_MM:
1800 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001801 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001802 Offset = Inst.getOperand(2);
1803 if (!Offset.isImm())
1804 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001805 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001806 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001807 if (OffsetToAlignment(Offset.getImm(),
1808 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001809 return Error(IDLoc, "branch to misaligned address");
1810 break;
1811 case Mips::BGEZ:
1812 case Mips::BGTZ:
1813 case Mips::BLEZ:
1814 case Mips::BLTZ:
1815 case Mips::BGEZAL:
1816 case Mips::BLTZAL:
1817 case Mips::BC1F:
1818 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001819 case Mips::BGEZ_MM:
1820 case Mips::BGTZ_MM:
1821 case Mips::BLEZ_MM:
1822 case Mips::BLTZ_MM:
1823 case Mips::BGEZAL_MM:
1824 case Mips::BLTZAL_MM:
1825 case Mips::BC1F_MM:
1826 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001827 case Mips::BC1EQZC_MMR6:
1828 case Mips::BC1NEZC_MMR6:
1829 case Mips::BC2EQZC_MMR6:
1830 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001831 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001832 Offset = Inst.getOperand(1);
1833 if (!Offset.isImm())
1834 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001835 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001836 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001837 if (OffsetToAlignment(Offset.getImm(),
1838 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001839 return Error(IDLoc, "branch to misaligned address");
1840 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001841 case Mips::BGEC: case Mips::BGEC_MMR6:
1842 case Mips::BLTC: case Mips::BLTC_MMR6:
1843 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1844 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1845 case Mips::BEQC: case Mips::BEQC_MMR6:
1846 case Mips::BNEC: case Mips::BNEC_MMR6:
1847 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1848 Offset = Inst.getOperand(2);
1849 if (!Offset.isImm())
1850 break; // We'll deal with this situation later on when applying fixups.
1851 if (!isIntN(18, Offset.getImm()))
1852 return Error(IDLoc, "branch target out of range");
1853 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1854 return Error(IDLoc, "branch to misaligned address");
1855 break;
1856 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1857 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1858 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1859 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1860 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1861 Offset = Inst.getOperand(1);
1862 if (!Offset.isImm())
1863 break; // We'll deal with this situation later on when applying fixups.
1864 if (!isIntN(18, Offset.getImm()))
1865 return Error(IDLoc, "branch target out of range");
1866 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1867 return Error(IDLoc, "branch to misaligned address");
1868 break;
1869 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1870 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1871 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1872 Offset = Inst.getOperand(1);
1873 if (!Offset.isImm())
1874 break; // We'll deal with this situation later on when applying fixups.
1875 if (!isIntN(23, Offset.getImm()))
1876 return Error(IDLoc, "branch target out of range");
1877 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1878 return Error(IDLoc, "branch to misaligned address");
1879 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001880 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001881 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001882 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001883 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001884 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1885 Offset = Inst.getOperand(1);
1886 if (!Offset.isImm())
1887 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001888 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001889 return Error(IDLoc, "branch target out of range");
1890 if (OffsetToAlignment(Offset.getImm(), 2LL))
1891 return Error(IDLoc, "branch to misaligned address");
1892 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001893 }
1894 }
1895
Daniel Sandersa84989a2014-06-16 13:25:35 +00001896 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1897 // We still accept it but it is a normal nop.
1898 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1899 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1900 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1901 "nop instruction");
1902 }
1903
Kai Nackee0245392015-01-27 19:11:28 +00001904 if (hasCnMips()) {
1905 const unsigned Opcode = Inst.getOpcode();
1906 MCOperand Opnd;
1907 int Imm;
1908
1909 switch (Opcode) {
1910 default:
1911 break;
1912
1913 case Mips::BBIT0:
1914 case Mips::BBIT032:
1915 case Mips::BBIT1:
1916 case Mips::BBIT132:
1917 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1918 // The offset is handled above
1919 Opnd = Inst.getOperand(1);
1920 if (!Opnd.isImm())
1921 return Error(IDLoc, "expected immediate operand kind");
1922 Imm = Opnd.getImm();
1923 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1924 Opcode == Mips::BBIT1 ? 63 : 31))
1925 return Error(IDLoc, "immediate operand value out of range");
1926 if (Imm > 31) {
1927 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1928 : Mips::BBIT132);
1929 Inst.getOperand(1).setImm(Imm - 32);
1930 }
1931 break;
1932
Kai Nackee0245392015-01-27 19:11:28 +00001933 case Mips::SEQi:
1934 case Mips::SNEi:
1935 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1936 Opnd = Inst.getOperand(2);
1937 if (!Opnd.isImm())
1938 return Error(IDLoc, "expected immediate operand kind");
1939 Imm = Opnd.getImm();
1940 if (!isInt<10>(Imm))
1941 return Error(IDLoc, "immediate operand value out of range");
1942 break;
1943 }
1944 }
1945
Simon Dardis509da1a2017-02-13 16:06:48 +00001946 // Warn on division by zero. We're checking here as all instructions get
1947 // processed here, not just the macros that need expansion.
1948 //
1949 // The MIPS backend models most of the divison instructions and macros as
1950 // three operand instructions. The pre-R6 divide instructions however have
1951 // two operands and explicitly define HI/LO as part of the instruction,
1952 // not in the operands.
1953 unsigned FirstOp = 1;
1954 unsigned SecondOp = 2;
1955 switch (Inst.getOpcode()) {
1956 default:
1957 break;
1958 case Mips::SDivIMacro:
1959 case Mips::UDivIMacro:
1960 case Mips::DSDivIMacro:
1961 case Mips::DUDivIMacro:
1962 if (Inst.getOperand(2).getImm() == 0) {
1963 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1964 Inst.getOperand(1).getReg() == Mips::ZERO_64)
1965 Warning(IDLoc, "dividing zero by zero");
1966 else
1967 Warning(IDLoc, "division by zero");
1968 }
1969 break;
1970 case Mips::DSDIV:
1971 case Mips::SDIV:
1972 case Mips::UDIV:
1973 case Mips::DUDIV:
1974 case Mips::UDIV_MM:
1975 case Mips::SDIV_MM:
1976 FirstOp = 0;
1977 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00001978 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00001979 case Mips::SDivMacro:
1980 case Mips::DSDivMacro:
1981 case Mips::UDivMacro:
1982 case Mips::DUDivMacro:
1983 case Mips::DIV:
1984 case Mips::DIVU:
1985 case Mips::DDIV:
1986 case Mips::DDIVU:
1987 case Mips::DIVU_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00001988 case Mips::DIV_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00001989 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
1990 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
1991 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
1992 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
1993 Warning(IDLoc, "dividing zero by zero");
1994 else
1995 Warning(IDLoc, "division by zero");
1996 }
1997 break;
1998 }
1999
Simon Atanasyan50485142016-12-12 17:40:26 +00002000 // For PIC code convert unconditional jump to unconditional branch.
2001 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
2002 inPicMode()) {
2003 MCInst BInst;
2004 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
2005 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2006 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2007 BInst.addOperand(Inst.getOperand(0));
2008 Inst = BInst;
2009 }
2010
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002011 // This expansion is not in a function called by tryExpandInstruction()
2012 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002013 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2014 inPicMode()) {
2015 warnIfNoMacro(IDLoc);
2016
2017 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2018
2019 // We can do this expansion if there's only 1 symbol in the argument
2020 // expression.
2021 if (countMCSymbolRefExpr(JalExpr) > 1)
2022 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2023
2024 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002025 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002026 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2027
2028 // FIXME: Add support for label+offset operands (currently causes an error).
2029 // FIXME: Add support for forward-declared local symbols.
2030 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002031 if (JalSym->isInSection() || JalSym->isTemporary() ||
Simon Atanasyan478220f2018-05-24 07:36:00 +00002032 (JalSym->isELF() &&
2033 cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002034 if (isABI_O32()) {
2035 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002036 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002037 // R_(MICRO)MIPS_GOT16 label
2038 // addiu $25, $25, 0
2039 // R_(MICRO)MIPS_LO16 label
2040 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002041 const MCExpr *Got16RelocExpr =
2042 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2043 const MCExpr *Lo16RelocExpr =
2044 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002045
Daniel Sandersa736b372016-04-29 13:33:12 +00002046 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2047 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2048 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2049 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002050 } else if (isABI_N32() || isABI_N64()) {
2051 // If it's a local symbol and the N32/N64 ABIs are being used,
2052 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002053 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002054 // R_(MICRO)MIPS_GOT_DISP label
2055 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002056 const MCExpr *GotDispRelocExpr =
2057 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002058
Daniel Sandersa736b372016-04-29 13:33:12 +00002059 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2060 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2061 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002062 }
2063 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002064 // If it's an external/weak symbol, we expand to:
2065 // lw/ld $25, 0($gp)
2066 // R_(MICRO)MIPS_CALL16 label
2067 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002068 const MCExpr *Call16RelocExpr =
2069 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002070
Daniel Sandersa736b372016-04-29 13:33:12 +00002071 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2072 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002073 }
2074
2075 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002076 if (IsCpRestoreSet && inMicroMipsMode())
2077 JalrInst.setOpcode(Mips::JALRS_MM);
2078 else
2079 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002080 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2081 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2082
Vladimir Stefanovic4433f932018-12-10 15:07:36 +00002083 if (EmitJalrReloc) {
2084 // As an optimization hint for the linker, before the JALR we add:
2085 // .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol
2086 // tmplabel:
2087 MCSymbol *TmpLabel = getContext().createTempSymbol();
2088 const MCExpr *TmpExpr = MCSymbolRefExpr::create(TmpLabel, getContext());
2089 const MCExpr *RelocJalrExpr =
2090 MCSymbolRefExpr::create(JalSym, MCSymbolRefExpr::VK_None,
2091 getContext(), IDLoc);
2092
2093 TOut.getStreamer().EmitRelocDirective(*TmpExpr,
2094 inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",
2095 RelocJalrExpr, IDLoc, *STI);
2096 TOut.getStreamer().EmitLabel(TmpLabel);
2097 }
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002098
2099 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002100 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002101 }
2102
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002103 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2104 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002105 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002106 // reference or immediate we may have to expand instructions.
2107 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002108 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002109 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2110 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002111 MCOperand &Op = Inst.getOperand(i);
2112 if (Op.isImm()) {
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00002113 int64_t MemOffset = Op.getImm();
Jack Carter9e65aa32013-03-22 00:05:30 +00002114 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002115 // Offset can't exceed 16bit value.
Simon Atanasyana1882672018-05-24 07:36:11 +00002116 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
Nirav Dave2364748a2016-09-16 18:30:20 +00002117 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002118 }
2119 } else if (Op.isExpr()) {
2120 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002121 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002122 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002123 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002124 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002125 // Expand symbol.
Simon Atanasyana1882672018-05-24 07:36:11 +00002126 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
Nirav Dave2364748a2016-09-16 18:30:20 +00002127 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002128 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002129 } else if (!isEvaluated(Expr)) {
Simon Atanasyana1882672018-05-24 07:36:11 +00002130 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
Nirav Dave2364748a2016-09-16 18:30:20 +00002131 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002132 }
2133 }
2134 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002135 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002136 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002137
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002138 if (inMicroMipsMode()) {
Simon Dardis6a319922018-05-25 16:15:48 +00002139 if (MCID.mayLoad() && Inst.getOpcode() != Mips::LWP_MM) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002140 // Try to create 16-bit GP relative load instruction.
2141 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2142 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2143 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2144 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2145 MCOperand &Op = Inst.getOperand(i);
2146 if (Op.isImm()) {
2147 int MemOffset = Op.getImm();
2148 MCOperand &DstReg = Inst.getOperand(0);
2149 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002150 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002151 getContext().getRegisterInfo()->getRegClass(
2152 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002153 (BaseReg.getReg() == Mips::GP ||
2154 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002155
Daniel Sandersa736b372016-04-29 13:33:12 +00002156 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2157 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002158 return false;
2159 }
2160 }
2161 }
2162 } // for
2163 } // if load
2164
2165 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2166
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002167 MCOperand Opnd;
2168 int Imm;
2169
2170 switch (Inst.getOpcode()) {
2171 default:
2172 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002173 case Mips::ADDIUSP_MM:
2174 Opnd = Inst.getOperand(0);
2175 if (!Opnd.isImm())
2176 return Error(IDLoc, "expected immediate operand kind");
2177 Imm = Opnd.getImm();
2178 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2179 Imm % 4 != 0)
2180 return Error(IDLoc, "immediate operand value out of range");
2181 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002182 case Mips::SLL16_MM:
2183 case Mips::SRL16_MM:
2184 Opnd = Inst.getOperand(2);
2185 if (!Opnd.isImm())
2186 return Error(IDLoc, "expected immediate operand kind");
2187 Imm = Opnd.getImm();
2188 if (Imm < 1 || Imm > 8)
2189 return Error(IDLoc, "immediate operand value out of range");
2190 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002191 case Mips::LI16_MM:
2192 Opnd = Inst.getOperand(1);
2193 if (!Opnd.isImm())
2194 return Error(IDLoc, "expected immediate operand kind");
2195 Imm = Opnd.getImm();
2196 if (Imm < -1 || Imm > 126)
2197 return Error(IDLoc, "immediate operand value out of range");
2198 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002199 case Mips::ADDIUR2_MM:
2200 Opnd = Inst.getOperand(2);
2201 if (!Opnd.isImm())
2202 return Error(IDLoc, "expected immediate operand kind");
2203 Imm = Opnd.getImm();
2204 if (!(Imm == 1 || Imm == -1 ||
2205 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2206 return Error(IDLoc, "immediate operand value out of range");
2207 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002208 case Mips::ANDI16_MM:
2209 Opnd = Inst.getOperand(2);
2210 if (!Opnd.isImm())
2211 return Error(IDLoc, "expected immediate operand kind");
2212 Imm = Opnd.getImm();
2213 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2214 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2215 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2216 return Error(IDLoc, "immediate operand value out of range");
2217 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002218 case Mips::LBU16_MM:
2219 Opnd = Inst.getOperand(2);
2220 if (!Opnd.isImm())
2221 return Error(IDLoc, "expected immediate operand kind");
2222 Imm = Opnd.getImm();
2223 if (Imm < -1 || Imm > 14)
2224 return Error(IDLoc, "immediate operand value out of range");
2225 break;
2226 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002227 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002228 Opnd = Inst.getOperand(2);
2229 if (!Opnd.isImm())
2230 return Error(IDLoc, "expected immediate operand kind");
2231 Imm = Opnd.getImm();
2232 if (Imm < 0 || Imm > 15)
2233 return Error(IDLoc, "immediate operand value out of range");
2234 break;
2235 case Mips::LHU16_MM:
2236 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002237 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002238 Opnd = Inst.getOperand(2);
2239 if (!Opnd.isImm())
2240 return Error(IDLoc, "expected immediate operand kind");
2241 Imm = Opnd.getImm();
2242 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2243 return Error(IDLoc, "immediate operand value out of range");
2244 break;
2245 case Mips::LW16_MM:
2246 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002247 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002248 Opnd = Inst.getOperand(2);
2249 if (!Opnd.isImm())
2250 return Error(IDLoc, "expected immediate operand kind");
2251 Imm = Opnd.getImm();
2252 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2253 return Error(IDLoc, "immediate operand value out of range");
2254 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002255 case Mips::ADDIUPC_MM:
Simon Dardis6a319922018-05-25 16:15:48 +00002256 Opnd = Inst.getOperand(1);
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002257 if (!Opnd.isImm())
2258 return Error(IDLoc, "expected immediate operand kind");
Simon Dardis6a319922018-05-25 16:15:48 +00002259 Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002260 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002261 return Error(IDLoc, "immediate operand value out of range");
2262 break;
Simon Dardis6a319922018-05-25 16:15:48 +00002263 case Mips::LWP_MM:
2264 case Mips::SWP_MM:
2265 if (Inst.getOperand(0).getReg() == Mips::RA)
2266 return Error(IDLoc, "invalid operand for instruction");
2267 break;
Simon Atanasyan852dd832018-09-19 18:46:21 +00002268 case Mips::MOVEP_MM:
2269 case Mips::MOVEP_MMR6: {
2270 unsigned R0 = Inst.getOperand(0).getReg();
2271 unsigned R1 = Inst.getOperand(1).getReg();
2272 bool RegPair = ((R0 == Mips::A1 && R1 == Mips::A2) ||
2273 (R0 == Mips::A1 && R1 == Mips::A3) ||
2274 (R0 == Mips::A2 && R1 == Mips::A3) ||
2275 (R0 == Mips::A0 && R1 == Mips::S5) ||
2276 (R0 == Mips::A0 && R1 == Mips::S6) ||
2277 (R0 == Mips::A0 && R1 == Mips::A1) ||
2278 (R0 == Mips::A0 && R1 == Mips::A2) ||
2279 (R0 == Mips::A0 && R1 == Mips::A3));
2280 if (!RegPair)
2281 return Error(IDLoc, "invalid operand for instruction");
2282 break;
2283 }
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002284 }
2285 }
2286
Daniel Sandersd8c07762016-04-18 12:35:36 +00002287 bool FillDelaySlot =
2288 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2289 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002290 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002291
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002292 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002293 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002294 switch (ExpandResult) {
2295 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002296 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002297 break;
2298 case MER_Success:
2299 break;
2300 case MER_Fail:
2301 return true;
2302 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002303
Daniel Sanderscda908a2016-05-16 09:10:13 +00002304 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2305 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002306 if (inMicroMipsMode()) {
Daniel Sanderscda908a2016-05-16 09:10:13 +00002307 TOut.setUsesMicroMips();
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002308 TOut.updateABIInfo(*this);
2309 }
Daniel Sanderscda908a2016-05-16 09:10:13 +00002310
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002311 // If this instruction has a delay slot and .set reorder is active,
2312 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002313 if (FillDelaySlot) {
Aleksandar Beserminji8abf6802019-01-09 15:58:02 +00002314 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00002315 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002316 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002317
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002318 if ((Inst.getOpcode() == Mips::JalOneReg ||
2319 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2320 isPicAndNotNxxAbi()) {
2321 if (IsCpRestoreSet) {
2322 // We need a NOP between the JALR and the LW:
2323 // If .set reorder has been used, we've already emitted a NOP.
2324 // If .set noreorder has been used, we need to emit a NOP at this point.
2325 if (!AssemblerOptions.back()->isReorder())
Aleksandar Beserminji8abf6802019-01-09 15:58:02 +00002326 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc,
Daniel Sandersa736b372016-04-29 13:33:12 +00002327 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002328
2329 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002330 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002331 } else
2332 Warning(IDLoc, "no .cprestore used in PIC mode");
2333 }
2334
Jack Carter9e65aa32013-03-22 00:05:30 +00002335 return false;
2336}
2337
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002338MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002339MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2340 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002341 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002342 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002343 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002344 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002345 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002346 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002347 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002348 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002349 case Mips::LoadAddrImm64:
2350 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2351 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2352 "expected immediate operand kind");
2353
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002354 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2355 Inst.getOperand(1),
2356 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002357 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002358 ? MER_Fail
2359 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002360 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002361 case Mips::LoadAddrReg64:
2362 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2363 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2364 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2365 "expected immediate operand kind");
2366
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002367 return expandLoadAddress(Inst.getOperand(0).getReg(),
2368 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2369 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002370 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002371 ? MER_Fail
2372 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002373 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002374 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002375 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2376 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002377 case Mips::SWM_MM:
2378 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002379 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2380 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002381 case Mips::JalOneReg:
2382 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002383 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002384 case Mips::BneImm:
2385 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002386 case Mips::BEQLImmMacro:
2387 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002388 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002389 case Mips::BLT:
2390 case Mips::BLE:
2391 case Mips::BGE:
2392 case Mips::BGT:
2393 case Mips::BLTU:
2394 case Mips::BLEU:
2395 case Mips::BGEU:
2396 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002397 case Mips::BLTL:
2398 case Mips::BLEL:
2399 case Mips::BGEL:
2400 case Mips::BGTL:
2401 case Mips::BLTUL:
2402 case Mips::BLEUL:
2403 case Mips::BGEUL:
2404 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002405 case Mips::BLTImmMacro:
2406 case Mips::BLEImmMacro:
2407 case Mips::BGEImmMacro:
2408 case Mips::BGTImmMacro:
2409 case Mips::BLTUImmMacro:
2410 case Mips::BLEUImmMacro:
2411 case Mips::BGEUImmMacro:
2412 case Mips::BGTUImmMacro:
2413 case Mips::BLTLImmMacro:
2414 case Mips::BLELImmMacro:
2415 case Mips::BGELImmMacro:
2416 case Mips::BGTLImmMacro:
2417 case Mips::BLTULImmMacro:
2418 case Mips::BLEULImmMacro:
2419 case Mips::BGEULImmMacro:
2420 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002421 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002422 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002423 case Mips::SDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002424 case Mips::SRemMacro:
2425 case Mips::SRemIMacro:
2426 return expandDivRem(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2427 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002428 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002429 case Mips::DSDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002430 case Mips::DSRemMacro:
2431 case Mips::DSRemIMacro:
2432 return expandDivRem(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2433 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002434 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002435 case Mips::UDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002436 case Mips::URemMacro:
2437 case Mips::URemIMacro:
2438 return expandDivRem(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2439 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002440 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002441 case Mips::DUDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002442 case Mips::DURemMacro:
2443 case Mips::DURemIMacro:
2444 return expandDivRem(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2445 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002446 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002447 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2448 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002449 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002450 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002451 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002452 case Mips::PseudoTRUNC_W_D:
2453 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2454 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002455
2456 case Mips::LoadImmSingleGPR:
2457 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2458 ? MER_Fail
2459 : MER_Success;
2460 case Mips::LoadImmSingleFGR:
2461 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2462 ? MER_Fail
2463 : MER_Success;
2464 case Mips::LoadImmDoubleGPR:
2465 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2466 ? MER_Fail
2467 : MER_Success;
2468 case Mips::LoadImmDoubleFGR:
2469 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2470 ? MER_Fail
2471 : MER_Success;
2472 case Mips::LoadImmDoubleFGR_32:
2473 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2474 ? MER_Fail
2475 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002476 case Mips::Ulh:
2477 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2478 case Mips::Ulhu:
2479 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002480 case Mips::Ush:
2481 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002482 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002483 case Mips::Usw:
2484 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002485 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002486 case Mips::NORImm64:
2487 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2488 case Mips::SLTImm64:
2489 if (isInt<16>(Inst.getOperand(2).getImm())) {
2490 Inst.setOpcode(Mips::SLTi64);
2491 return MER_NotAMacro;
2492 }
2493 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2494 case Mips::SLTUImm64:
2495 if (isInt<16>(Inst.getOperand(2).getImm())) {
2496 Inst.setOpcode(Mips::SLTiu64);
2497 return MER_NotAMacro;
2498 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002499 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002500 case Mips::ADDi: case Mips::ADDi_MM:
2501 case Mips::ADDiu: case Mips::ADDiu_MM:
2502 case Mips::SLTi: case Mips::SLTi_MM:
2503 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002504 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2505 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2506 int64_t ImmValue = Inst.getOperand(2).getImm();
2507 if (isInt<16>(ImmValue))
2508 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002509 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2510 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002511 }
2512 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002513 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2514 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2515 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002516 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2517 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2518 int64_t ImmValue = Inst.getOperand(2).getImm();
2519 if (isUInt<16>(ImmValue))
2520 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002521 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2522 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002523 }
2524 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002525 case Mips::ROL:
2526 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002527 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002528 case Mips::ROLImm:
2529 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002530 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002531 case Mips::DROL:
2532 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002533 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002534 case Mips::DROLImm:
2535 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002536 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002537 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002538 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002539 case Mips::MULImmMacro:
2540 case Mips::DMULImmMacro:
2541 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2542 case Mips::MULOMacro:
2543 case Mips::DMULOMacro:
2544 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2545 case Mips::MULOUMacro:
2546 case Mips::DMULOUMacro:
2547 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2548 case Mips::DMULMacro:
2549 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002550 case Mips::LDMacro:
2551 case Mips::SDMacro:
2552 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2553 Inst.getOpcode() == Mips::LDMacro)
2554 ? MER_Fail
2555 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002556 case Mips::SEQMacro:
2557 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2558 case Mips::SEQIMacro:
2559 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisde5ed0c2017-11-14 22:26:42 +00002560 case Mips::MFTC0: case Mips::MTTC0:
2561 case Mips::MFTGPR: case Mips::MTTGPR:
2562 case Mips::MFTLO: case Mips::MTTLO:
2563 case Mips::MFTHI: case Mips::MTTHI:
2564 case Mips::MFTACX: case Mips::MTTACX:
2565 case Mips::MFTDSP: case Mips::MTTDSP:
2566 case Mips::MFTC1: case Mips::MTTC1:
2567 case Mips::MFTHC1: case Mips::MTTHC1:
2568 case Mips::CFTC1: case Mips::CTTC1:
2569 return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002570 }
Jack Carter30a59822012-10-04 04:03:53 +00002571}
Jack Carter92995f12012-10-06 00:53:28 +00002572
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002573bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002574 MCStreamer &Out,
2575 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002576 MipsTargetStreamer &TOut = getTargetStreamer();
2577
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002578 // Create a JALR instruction which is going to replace the pseudo-JAL.
2579 MCInst JalrInst;
2580 JalrInst.setLoc(IDLoc);
2581 const MCOperand FirstRegOp = Inst.getOperand(0);
2582 const unsigned Opcode = Inst.getOpcode();
2583
2584 if (Opcode == Mips::JalOneReg) {
2585 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002586 if (IsCpRestoreSet && inMicroMipsMode()) {
2587 JalrInst.setOpcode(Mips::JALRS16_MM);
2588 JalrInst.addOperand(FirstRegOp);
2589 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002590 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002591 JalrInst.addOperand(FirstRegOp);
2592 } else {
2593 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002594 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002595 JalrInst.addOperand(FirstRegOp);
2596 }
2597 } else if (Opcode == Mips::JalTwoReg) {
2598 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002599 if (IsCpRestoreSet && inMicroMipsMode())
2600 JalrInst.setOpcode(Mips::JALRS_MM);
2601 else
2602 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002603 JalrInst.addOperand(FirstRegOp);
2604 const MCOperand SecondRegOp = Inst.getOperand(1);
2605 JalrInst.addOperand(SecondRegOp);
2606 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002607 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002608
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002609 // If .set reorder is active and branch instruction has a delay slot,
2610 // emit a NOP after it.
2611 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002612 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Aleksandar Beserminji8abf6802019-01-09 15:58:02 +00002613 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst), IDLoc,
Daniel Sandersa736b372016-04-29 13:33:12 +00002614 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002615
2616 return false;
2617}
2618
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002619/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002620template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002621 unsigned BitNum = findFirstSet(x);
2622
2623 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2624}
2625
2626/// Load (or add) an immediate into a register.
2627///
2628/// @param ImmValue The immediate to load.
2629/// @param DstReg The register that will hold the immediate.
2630/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2631/// for a simple initialization.
2632/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2633/// @param IsAddress True if the immediate represents an address. False if it
2634/// is an integer.
2635/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002636bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002637 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002638 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2639 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002640 MipsTargetStreamer &TOut = getTargetStreamer();
2641
Toma Tabacu00e98672015-05-01 12:19:27 +00002642 if (!Is32BitImm && !isGP64bit()) {
2643 Error(IDLoc, "instruction requires a 64-bit architecture");
2644 return true;
2645 }
2646
Daniel Sanders03f9c012015-07-14 12:24:22 +00002647 if (Is32BitImm) {
2648 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2649 // Sign extend up to 64-bit so that the predicates match the hardware
2650 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2651 // true.
2652 ImmValue = SignExtend64<32>(ImmValue);
2653 } else {
2654 Error(IDLoc, "instruction requires a 32-bit immediate");
2655 return true;
2656 }
2657 }
2658
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002659 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2660 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2661
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002662 bool UseSrcReg = false;
2663 if (SrcReg != Mips::NoRegister)
2664 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002665
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002666 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002667 if (UseSrcReg &&
2668 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002669 // At this point we need AT to perform the expansions and we exit if it is
2670 // not available.
2671 unsigned ATReg = getATReg(IDLoc);
2672 if (!ATReg)
2673 return true;
2674 TmpReg = ATReg;
2675 }
2676
Daniel Sanders03f9c012015-07-14 12:24:22 +00002677 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002678 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002679 SrcReg = ZeroReg;
2680
2681 // This doesn't quite follow the usual ABI expectations for N32 but matches
2682 // traditional assembler behaviour. N32 would normally use addiu for both
2683 // integers and addresses.
2684 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002685 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002686 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002687 }
2688
Daniel Sandersa736b372016-04-29 13:33:12 +00002689 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002690 return false;
2691 }
2692
2693 if (isUInt<16>(ImmValue)) {
2694 unsigned TmpReg = DstReg;
2695 if (SrcReg == DstReg) {
2696 TmpReg = getATReg(IDLoc);
2697 if (!TmpReg)
2698 return true;
2699 }
2700
Daniel Sandersa736b372016-04-29 13:33:12 +00002701 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002702 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002703 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002704 return false;
2705 }
2706
2707 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002708 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002709
Toma Tabacu79588102015-04-29 10:19:56 +00002710 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2711 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002712 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002713 // Traditional behaviour seems to special case this particular value. It's
2714 // not clear why other masks are handled differently.
2715 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002716 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2717 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002718 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002719 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002720 return false;
2721 }
2722
2723 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002724 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002725 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2726 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002727 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002728 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002729 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002730 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002731 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002732 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002733
Daniel Sandersa736b372016-04-29 13:33:12 +00002734 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002735 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002736 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002737 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002738 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002739 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002740 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002741
2742 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2743 if (Is32BitImm) {
2744 Error(IDLoc, "instruction requires a 32-bit immediate");
2745 return true;
2746 }
2747
2748 // Traditionally, these immediates are shifted as little as possible and as
2749 // such we align the most significant bit to bit 15 of our temporary.
2750 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2751 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2752 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2753 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002754 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2755 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002756
2757 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002758 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002759
2760 return false;
2761 }
2762
2763 warnIfNoMacro(IDLoc);
2764
2765 // The remaining case is packed with a sequence of dsll and ori with zeros
2766 // being omitted and any neighbouring dsll's being coalesced.
2767 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2768
2769 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2770 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002771 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002772 return false;
2773
2774 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2775 // skip it and defer the shift to the next chunk.
2776 unsigned ShiftCarriedForwards = 16;
2777 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2778 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2779
2780 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002781 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2782 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002783 ShiftCarriedForwards = 0;
2784 }
2785
2786 ShiftCarriedForwards += 16;
2787 }
2788 ShiftCarriedForwards -= 16;
2789
2790 // Finish any remaining shifts left by trailing zeros.
2791 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002792 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002793
2794 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002795 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002796
Matheus Almeida3813d572014-06-19 14:39:14 +00002797 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002798}
Jack Carter92995f12012-10-06 00:53:28 +00002799
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002800bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002801 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002802 const MCOperand &ImmOp = Inst.getOperand(1);
2803 assert(ImmOp.isImm() && "expected immediate operand kind");
2804 const MCOperand &DstRegOp = Inst.getOperand(0);
2805 assert(DstRegOp.isReg() && "expected register operand kind");
2806
2807 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002808 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002809 return true;
2810
2811 return false;
2812}
2813
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002814bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2815 const MCOperand &Offset,
2816 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002817 MCStreamer &Out,
2818 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002819 // la can't produce a usable address when addresses are 64-bit.
2820 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2821 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2822 // We currently can't do this because we depend on the equality
2823 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2824 Error(IDLoc, "la used to load 64-bit address");
2825 // Continue as if we had 'dla' instead.
2826 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002827 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002828 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002829
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002830 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002831 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002832 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002833 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002834 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002835
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002836 if (!Offset.isImm())
2837 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002838 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002839
Scott Egerton24557012016-01-21 15:11:01 +00002840 if (!ABI.ArePtrs64bit()) {
2841 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2842 Is32BitAddress = true;
2843 }
2844
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002845 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002846 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002847}
2848
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002849bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2850 unsigned DstReg, unsigned SrcReg,
2851 bool Is32BitSym, SMLoc IDLoc,
2852 MCStreamer &Out,
2853 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002854 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002855 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002856 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002857 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002858
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002859 if (inPicMode() && ABI.IsO32()) {
2860 MCValue Res;
2861 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2862 Error(IDLoc, "expected relocatable expression");
2863 return true;
2864 }
2865 if (Res.getSymB() != nullptr) {
2866 Error(IDLoc, "expected relocatable expression with only one symbol");
2867 return true;
2868 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002869
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002870 // The case where the result register is $25 is somewhat special. If the
2871 // symbol in the final relocation is external and not modified with a
2872 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2873 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002874 Res.getConstant() == 0 &&
2875 !(Res.getSymA()->getSymbol().isInSection() ||
2876 Res.getSymA()->getSymbol().isTemporary() ||
2877 (Res.getSymA()->getSymbol().isELF() &&
2878 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2879 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002880 const MCExpr *CallExpr =
2881 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2882 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2883 MCOperand::createExpr(CallExpr), IDLoc, STI);
2884 return false;
2885 }
2886
2887 // The remaining cases are:
2888 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2889 // >addiu $tmp, $tmp, %lo(offset)
2890 // >addiu $rd, $tmp, $rs
2891 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2892 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2893 // >addiu $rd, $tmp, $rs
2894 // The addiu's marked with a '>' may be omitted if they are redundant. If
2895 // this happens then the last instruction must use $rd as the result
2896 // register.
2897 const MipsMCExpr *GotExpr =
2898 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2899 const MCExpr *LoExpr = nullptr;
2900 if (Res.getSymA()->getSymbol().isInSection() ||
2901 Res.getSymA()->getSymbol().isTemporary())
2902 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2903 else if (Res.getConstant() != 0) {
2904 // External symbols fully resolve the symbol with just the %got(symbol)
2905 // but we must still account for any offset to the symbol for expressions
2906 // like symbol+8.
2907 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2908 }
2909
2910 unsigned TmpReg = DstReg;
2911 if (UseSrcReg &&
2912 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2913 SrcReg)) {
2914 // If $rs is the same as $rd, we need to use AT.
2915 // If it is not available we exit.
2916 unsigned ATReg = getATReg(IDLoc);
2917 if (!ATReg)
2918 return true;
2919 TmpReg = ATReg;
2920 }
2921
2922 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2923 MCOperand::createExpr(GotExpr), IDLoc, STI);
2924
2925 if (LoExpr)
2926 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2927 IDLoc, STI);
2928
2929 if (UseSrcReg)
2930 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2931
2932 return false;
2933 }
2934
Simon Dardisda96c432017-06-30 15:44:27 +00002935 if (inPicMode() && ABI.ArePtrs64bit()) {
2936 MCValue Res;
2937 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2938 Error(IDLoc, "expected relocatable expression");
2939 return true;
2940 }
2941 if (Res.getSymB() != nullptr) {
2942 Error(IDLoc, "expected relocatable expression with only one symbol");
2943 return true;
2944 }
2945
2946 // The case where the result register is $25 is somewhat special. If the
2947 // symbol in the final relocation is external and not modified with a
2948 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2949 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2950 Res.getConstant() == 0 &&
2951 !(Res.getSymA()->getSymbol().isInSection() ||
2952 Res.getSymA()->getSymbol().isTemporary() ||
2953 (Res.getSymA()->getSymbol().isELF() &&
2954 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2955 ELF::STB_LOCAL))) {
2956 const MCExpr *CallExpr =
2957 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2958 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2959 MCOperand::createExpr(CallExpr), IDLoc, STI);
2960 return false;
2961 }
2962
2963 // The remaining cases are:
2964 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2965 // >daddiu $tmp, $tmp, offset
2966 // >daddu $rd, $tmp, $rs
2967 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2968 // this happens then the last instruction must use $rd as the result
2969 // register.
2970 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2971 Res.getSymA(),
2972 getContext());
2973 const MCExpr *LoExpr = nullptr;
2974 if (Res.getConstant() != 0) {
2975 // Symbols fully resolve with just the %got_disp(symbol) but we
2976 // must still account for any offset to the symbol for
2977 // expressions like symbol+8.
2978 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2979
2980 // FIXME: Offsets greater than 16 bits are not yet implemented.
2981 // FIXME: The correct range is a 32-bit sign-extended number.
2982 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2983 Error(IDLoc, "macro instruction uses large offset, which is not "
2984 "currently supported");
2985 return true;
2986 }
2987 }
2988
2989 unsigned TmpReg = DstReg;
2990 if (UseSrcReg &&
2991 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2992 SrcReg)) {
2993 // If $rs is the same as $rd, we need to use AT.
2994 // If it is not available we exit.
2995 unsigned ATReg = getATReg(IDLoc);
2996 if (!ATReg)
2997 return true;
2998 TmpReg = ATReg;
2999 }
3000
3001 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
3002 MCOperand::createExpr(GotExpr), IDLoc, STI);
3003
3004 if (LoExpr)
3005 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3006 IDLoc, STI);
3007
3008 if (UseSrcReg)
3009 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
3010
3011 return false;
3012 }
3013
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003014 const MipsMCExpr *HiExpr =
3015 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
3016 const MipsMCExpr *LoExpr =
3017 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00003018
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003019 // This is the 64-bit symbol address expansion.
3020 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00003021 // We need AT for the 64-bit expansion in the cases where the optional
3022 // source register is the destination register and for the superscalar
3023 // scheduled form.
3024 //
3025 // If it is not available we exit if the destination is the same as the
3026 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003027
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003028 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003029 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003030 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003031 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003032
Simon Dardis3aa8a902017-02-06 12:43:46 +00003033 bool RdRegIsRsReg =
3034 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
3035
3036 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
3037 unsigned ATReg = getATReg(IDLoc);
3038
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003039 // If $rs is the same as $rd:
3040 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
3041 // daddiu $at, $at, %higher(sym)
3042 // dsll $at, $at, 16
3043 // daddiu $at, $at, %hi(sym)
3044 // dsll $at, $at, 16
3045 // daddiu $at, $at, %lo(sym)
3046 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00003047 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3048 STI);
3049 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3050 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3051 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3052 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3053 IDLoc, STI);
3054 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3055 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3056 IDLoc, STI);
3057 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003058
3059 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00003060 } else if (canUseATReg() && !RdRegIsRsReg) {
3061 unsigned ATReg = getATReg(IDLoc);
3062
3063 // If the $rs is different from $rd or if $rs isn't specified and we
3064 // have $at available:
3065 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3066 // lui $at, %hi(sym)
3067 // daddiu $rd, $rd, %higher(sym)
3068 // daddiu $at, $at, %lo(sym)
3069 // dsll32 $rd, $rd, 0
3070 // daddu $rd, $rd, $at
3071 // (daddu $rd, $rd, $rs)
3072 //
3073 // Which is preferred for superscalar issue.
3074 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3075 STI);
3076 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3077 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3078 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3079 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3080 IDLoc, STI);
3081 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3082 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3083 if (UseSrcReg)
3084 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3085
3086 return false;
3087 } else if (!canUseATReg() && !RdRegIsRsReg) {
3088 // Otherwise, synthesize the address in the destination register
3089 // serially:
3090 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3091 // daddiu $rd, $rd, %higher(sym)
3092 // dsll $rd, $rd, 16
3093 // daddiu $rd, $rd, %hi(sym)
3094 // dsll $rd, $rd, 16
3095 // daddiu $rd, $rd, %lo(sym)
3096 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3097 STI);
3098 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3099 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3100 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3101 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3102 MCOperand::createExpr(HiExpr), IDLoc, STI);
3103 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3104 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3105 MCOperand::createExpr(LoExpr), IDLoc, STI);
3106 if (UseSrcReg)
3107 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3108
3109 return false;
3110 } else {
3111 // We have a case where SrcReg == DstReg and we don't have $at
3112 // available. We can't expand this case, so error out appropriately.
3113 assert(SrcReg == DstReg && !canUseATReg() &&
3114 "Could have expanded dla but didn't?");
3115 reportParseError(IDLoc,
3116 "pseudo-instruction requires $at, which is not available");
3117 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003118 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003119 }
3120
3121 // And now, the 32-bit symbol address expansion:
3122 // If $rs is the same as $rd:
3123 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3124 // ori $at, $at, %lo(sym)
3125 // addu $rd, $at, $rd
3126 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3127 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3128 // ori $rd, $rd, %lo(sym)
3129 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003130 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003131 if (UseSrcReg &&
3132 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003133 // If $rs is the same as $rd, we need to use AT.
3134 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003135 unsigned ATReg = getATReg(IDLoc);
3136 if (!ATReg)
3137 return true;
3138 TmpReg = ATReg;
3139 }
3140
Daniel Sandersa736b372016-04-29 13:33:12 +00003141 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3142 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3143 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003144
Toma Tabacufb9d1252015-06-22 12:08:39 +00003145 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003146 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003147 else
Scott Egerton24557012016-01-21 15:11:01 +00003148 assert(
3149 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003150
Toma Tabacu674825c2015-06-16 12:16:24 +00003151 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003152}
3153
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003154// Each double-precision register DO-D15 overlaps with two of the single
3155// precision registers F0-F31. As an example, all of the following hold true:
3156// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3157static unsigned nextReg(unsigned Reg) {
3158 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3159 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3160 switch (Reg) {
3161 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3162 case Mips::ZERO: return Mips::AT;
3163 case Mips::AT: return Mips::V0;
3164 case Mips::V0: return Mips::V1;
3165 case Mips::V1: return Mips::A0;
3166 case Mips::A0: return Mips::A1;
3167 case Mips::A1: return Mips::A2;
3168 case Mips::A2: return Mips::A3;
3169 case Mips::A3: return Mips::T0;
3170 case Mips::T0: return Mips::T1;
3171 case Mips::T1: return Mips::T2;
3172 case Mips::T2: return Mips::T3;
3173 case Mips::T3: return Mips::T4;
3174 case Mips::T4: return Mips::T5;
3175 case Mips::T5: return Mips::T6;
3176 case Mips::T6: return Mips::T7;
3177 case Mips::T7: return Mips::S0;
3178 case Mips::S0: return Mips::S1;
3179 case Mips::S1: return Mips::S2;
3180 case Mips::S2: return Mips::S3;
3181 case Mips::S3: return Mips::S4;
3182 case Mips::S4: return Mips::S5;
3183 case Mips::S5: return Mips::S6;
3184 case Mips::S6: return Mips::S7;
3185 case Mips::S7: return Mips::T8;
3186 case Mips::T8: return Mips::T9;
3187 case Mips::T9: return Mips::K0;
3188 case Mips::K0: return Mips::K1;
3189 case Mips::K1: return Mips::GP;
3190 case Mips::GP: return Mips::SP;
3191 case Mips::SP: return Mips::FP;
3192 case Mips::FP: return Mips::RA;
3193 case Mips::RA: return Mips::ZERO;
3194 case Mips::D0: return Mips::F1;
3195 case Mips::D1: return Mips::F3;
3196 case Mips::D2: return Mips::F5;
3197 case Mips::D3: return Mips::F7;
3198 case Mips::D4: return Mips::F9;
3199 case Mips::D5: return Mips::F11;
3200 case Mips::D6: return Mips::F13;
3201 case Mips::D7: return Mips::F15;
3202 case Mips::D8: return Mips::F17;
3203 case Mips::D9: return Mips::F19;
3204 case Mips::D10: return Mips::F21;
3205 case Mips::D11: return Mips::F23;
3206 case Mips::D12: return Mips::F25;
3207 case Mips::D13: return Mips::F27;
3208 case Mips::D14: return Mips::F29;
3209 case Mips::D15: return Mips::F31;
3210 }
3211}
3212
3213// FIXME: This method is too general. In principle we should compute the number
3214// of instructions required to synthesize the immediate inline compared to
3215// synthesizing the address inline and relying on non .text sections.
3216// For static O32 and N32 this may yield a small benefit, for static N64 this is
3217// likely to yield a much larger benefit as we have to synthesize a 64bit
3218// address to load a 64 bit value.
3219bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3220 MCSymbol *Sym) {
3221 unsigned ATReg = getATReg(IDLoc);
3222 if (!ATReg)
3223 return true;
3224
3225 if(IsPicEnabled) {
3226 const MCExpr *GotSym =
3227 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3228 const MipsMCExpr *GotExpr =
3229 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3230
3231 if(isABI_O32() || isABI_N32()) {
3232 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3233 IDLoc, STI);
3234 } else { //isABI_N64()
3235 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3236 IDLoc, STI);
3237 }
3238 } else { //!IsPicEnabled
3239 const MCExpr *HiSym =
3240 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3241 const MipsMCExpr *HiExpr =
3242 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3243
3244 // FIXME: This is technically correct but gives a different result to gas,
3245 // but gas is incomplete there (it has a fixme noting it doesn't work with
3246 // 64-bit addresses).
3247 // FIXME: With -msym32 option, the address expansion for N64 should probably
3248 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3249 // symbol's value is considered sign extended.
3250 if(isABI_O32() || isABI_N32()) {
3251 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3252 } else { //isABI_N64()
3253 const MCExpr *HighestSym =
3254 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3255 const MipsMCExpr *HighestExpr =
3256 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3257 const MCExpr *HigherSym =
3258 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3259 const MipsMCExpr *HigherExpr =
3260 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3261
3262 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3263 STI);
3264 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3265 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3266 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3267 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3268 IDLoc, STI);
3269 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3270 }
3271 }
3272 return false;
3273}
3274
3275bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3276 bool Is64FPU, SMLoc IDLoc,
3277 MCStreamer &Out,
3278 const MCSubtargetInfo *STI) {
3279 MipsTargetStreamer &TOut = getTargetStreamer();
3280 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3281 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3282 "Invalid instruction operand.");
3283
3284 unsigned FirstReg = Inst.getOperand(0).getReg();
3285 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3286
3287 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3288 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3289 // exponent field), convert it to double (e.g. 1 to 1.0)
3290 if ((HiImmOp64 & 0x7ff00000) == 0) {
3291 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3292 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3293 }
3294
3295 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3296 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3297
3298 if (IsSingle) {
3299 // Conversion of a double in an uint64_t to a float in a uint32_t,
3300 // retaining the bit pattern of a float.
3301 uint32_t ImmOp32;
3302 double doubleImm = BitsToDouble(ImmOp64);
3303 float tmp_float = static_cast<float>(doubleImm);
3304 ImmOp32 = FloatToBits(tmp_float);
3305
3306 if (IsGPR) {
3307 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3308 Out, STI))
3309 return true;
3310 return false;
3311 } else {
3312 unsigned ATReg = getATReg(IDLoc);
3313 if (!ATReg)
3314 return true;
3315 if (LoImmOp64 == 0) {
3316 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3317 Out, STI))
3318 return true;
3319 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3320 return false;
3321 }
3322
3323 MCSection *CS = getStreamer().getCurrentSectionOnly();
3324 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3325 // where appropriate.
3326 MCSection *ReadOnlySection = getContext().getELFSection(
3327 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3328
3329 MCSymbol *Sym = getContext().createTempSymbol();
3330 const MCExpr *LoSym =
3331 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3332 const MipsMCExpr *LoExpr =
3333 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3334
3335 getStreamer().SwitchSection(ReadOnlySection);
3336 getStreamer().EmitLabel(Sym, IDLoc);
3337 getStreamer().EmitIntValue(ImmOp32, 4);
3338 getStreamer().SwitchSection(CS);
3339
3340 if(emitPartialAddress(TOut, IDLoc, Sym))
3341 return true;
3342 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3343 MCOperand::createExpr(LoExpr), IDLoc, STI);
3344 }
3345 return false;
3346 }
3347
3348 // if(!IsSingle)
3349 unsigned ATReg = getATReg(IDLoc);
3350 if (!ATReg)
3351 return true;
3352
3353 if (IsGPR) {
3354 if (LoImmOp64 == 0) {
3355 if(isABI_N32() || isABI_N64()) {
3356 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3357 IDLoc, Out, STI))
3358 return true;
3359 return false;
3360 } else {
3361 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3362 IDLoc, Out, STI))
3363 return true;
3364
3365 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3366 IDLoc, Out, STI))
3367 return true;
3368 return false;
3369 }
3370 }
3371
3372 MCSection *CS = getStreamer().getCurrentSectionOnly();
3373 MCSection *ReadOnlySection = getContext().getELFSection(
3374 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3375
3376 MCSymbol *Sym = getContext().createTempSymbol();
3377 const MCExpr *LoSym =
3378 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3379 const MipsMCExpr *LoExpr =
3380 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3381
3382 getStreamer().SwitchSection(ReadOnlySection);
3383 getStreamer().EmitLabel(Sym, IDLoc);
3384 getStreamer().EmitIntValue(HiImmOp64, 4);
3385 getStreamer().EmitIntValue(LoImmOp64, 4);
3386 getStreamer().SwitchSection(CS);
3387
3388 if(emitPartialAddress(TOut, IDLoc, Sym))
3389 return true;
3390 if(isABI_N64())
3391 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3392 MCOperand::createExpr(LoExpr), IDLoc, STI);
3393 else
3394 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3395 MCOperand::createExpr(LoExpr), IDLoc, STI);
3396
3397 if(isABI_N32() || isABI_N64())
3398 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3399 else {
3400 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3401 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3402 }
3403 return false;
3404 } else { // if(!IsGPR && !IsSingle)
3405 if ((LoImmOp64 == 0) &&
3406 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3407 // FIXME: In the case where the constant is zero, we can load the
3408 // register directly from the zero register.
3409 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3410 Out, STI))
3411 return true;
3412 if (isABI_N32() || isABI_N64())
3413 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3414 else if (hasMips32r2()) {
3415 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3416 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3417 } else {
3418 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3419 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3420 }
3421 return false;
3422 }
3423
3424 MCSection *CS = getStreamer().getCurrentSectionOnly();
3425 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3426 // where appropriate.
3427 MCSection *ReadOnlySection = getContext().getELFSection(
3428 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3429
3430 MCSymbol *Sym = getContext().createTempSymbol();
3431 const MCExpr *LoSym =
3432 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3433 const MipsMCExpr *LoExpr =
3434 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3435
3436 getStreamer().SwitchSection(ReadOnlySection);
3437 getStreamer().EmitLabel(Sym, IDLoc);
3438 getStreamer().EmitIntValue(HiImmOp64, 4);
3439 getStreamer().EmitIntValue(LoImmOp64, 4);
3440 getStreamer().SwitchSection(CS);
3441
3442 if(emitPartialAddress(TOut, IDLoc, Sym))
3443 return true;
3444 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3445 MCOperand::createExpr(LoExpr), IDLoc, STI);
3446 }
3447 return false;
3448}
3449
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003450bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3451 MCStreamer &Out,
3452 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003453 MipsTargetStreamer &TOut = getTargetStreamer();
3454
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003455 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3456 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003457
3458 MCOperand Offset = Inst.getOperand(0);
3459 if (Offset.isExpr()) {
3460 Inst.clear();
3461 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003462 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3463 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3464 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003465 } else {
3466 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003467 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003468 // If offset fits into 11 bits then this instruction becomes microMIPS
3469 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003470 if (inMicroMipsMode())
3471 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003472 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003473 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003474 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003475 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003476 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003477 Inst.clear();
3478 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003479 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3480 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3481 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003482 }
3483 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003484 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003485
Zoran Jovanovicada70912015-09-07 11:56:37 +00003486 // If .set reorder is active and branch instruction has a delay slot,
3487 // emit a NOP after it.
3488 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3489 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003490 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003491
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003492 return false;
3493}
3494
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003495bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3496 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003497 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003498 const MCOperand &DstRegOp = Inst.getOperand(0);
3499 assert(DstRegOp.isReg() && "expected register operand kind");
3500
3501 const MCOperand &ImmOp = Inst.getOperand(1);
3502 assert(ImmOp.isImm() && "expected immediate operand kind");
3503
3504 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003505 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3506 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003507
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003508 bool IsLikely = false;
3509
Toma Tabacue1e460d2015-06-11 10:36:10 +00003510 unsigned OpCode = 0;
3511 switch(Inst.getOpcode()) {
3512 case Mips::BneImm:
3513 OpCode = Mips::BNE;
3514 break;
3515 case Mips::BeqImm:
3516 OpCode = Mips::BEQ;
3517 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003518 case Mips::BEQLImmMacro:
3519 OpCode = Mips::BEQL;
3520 IsLikely = true;
3521 break;
3522 case Mips::BNELImmMacro:
3523 OpCode = Mips::BNEL;
3524 IsLikely = true;
3525 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003526 default:
3527 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3528 break;
3529 }
3530
3531 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003532 if (ImmValue == 0) {
3533 if (IsLikely) {
3534 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3535 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3536 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3537 } else
3538 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3539 STI);
3540 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003541 warnIfNoMacro(IDLoc);
3542
3543 unsigned ATReg = getATReg(IDLoc);
3544 if (!ATReg)
3545 return true;
3546
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003547 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003548 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003549 return true;
3550
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003551 if (IsLikely) {
3552 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3553 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3554 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3555 } else
3556 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003557 }
3558 return false;
3559}
3560
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003561void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Simon Atanasyana1882672018-05-24 07:36:11 +00003562 const MCSubtargetInfo *STI, bool IsLoad) {
Simon Atanasyanbe8a42e2018-05-24 07:36:06 +00003563 const MCOperand &DstRegOp = Inst.getOperand(0);
3564 assert(DstRegOp.isReg() && "expected register operand kind");
3565 const MCOperand &BaseRegOp = Inst.getOperand(1);
3566 assert(BaseRegOp.isReg() && "expected register operand kind");
3567 const MCOperand &OffsetOp = Inst.getOperand(2);
Daniel Sandersfba875f2016-04-29 13:43:45 +00003568
Simon Atanasyanbe8a42e2018-05-24 07:36:06 +00003569 MipsTargetStreamer &TOut = getTargetStreamer();
3570 unsigned DstReg = DstRegOp.getReg();
3571 unsigned BaseReg = BaseRegOp.getReg();
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003572 unsigned TmpReg = DstReg;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003573
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003574 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003575 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3576 unsigned DstRegClassID =
3577 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3578 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3579 (DstRegClassID == Mips::GPR64RegClassID);
3580
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00003581 if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003582 // At this point we need AT to perform the expansions
3583 // and we exit if it is not available.
3584 TmpReg = getATReg(IDLoc);
3585 if (!TmpReg)
3586 return;
3587 }
3588
Simon Atanasyana1882672018-05-24 07:36:11 +00003589 if (OffsetOp.isImm()) {
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00003590 int64_t LoOffset = OffsetOp.getImm() & 0xffff;
3591 int64_t HiOffset = OffsetOp.getImm() & ~0xffff;
3592
3593 // If msb of LoOffset is 1(negative number) we must increment
3594 // HiOffset to account for the sign-extension of the low part.
3595 if (LoOffset & 0x8000)
3596 HiOffset += 0x10000;
3597
3598 bool IsLargeOffset = HiOffset != 0;
3599
3600 if (IsLargeOffset) {
3601 bool Is32BitImm = (HiOffset >> 32) == 0;
3602 if (loadImmediate(HiOffset, TmpReg, Mips::NoRegister, Is32BitImm, true,
3603 IDLoc, Out, STI))
3604 return;
3605 }
3606
3607 if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)
3608 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg,
3609 BaseReg, IDLoc, STI);
3610 TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, LoOffset, IDLoc, STI);
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003611 } else {
3612 assert(OffsetOp.isExpr() && "expected expression operand kind");
3613 const MCExpr *ExprOffset = OffsetOp.getExpr();
3614 MCOperand LoOperand = MCOperand::createExpr(
3615 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3616 MCOperand HiOperand = MCOperand::createExpr(
3617 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00003618
3619 if (IsLoad)
3620 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3621 LoOperand, TmpReg, IDLoc, STI);
3622 else
3623 TOut.emitStoreWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3624 LoOperand, TmpReg, IDLoc, STI);
Daniel Sandersfba875f2016-04-29 13:43:45 +00003625 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003626}
3627
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003628bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3629 MCStreamer &Out,
3630 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003631 unsigned OpNum = Inst.getNumOperands();
3632 unsigned Opcode = Inst.getOpcode();
3633 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3634
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003635 assert(Inst.getOperand(OpNum - 1).isImm() &&
3636 Inst.getOperand(OpNum - 2).isReg() &&
3637 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003638
3639 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3640 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003641 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3642 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3643 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3644 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003645 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003646 if (inMicroMipsMode() && hasMips32r6())
3647 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3648 else
3649 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3650 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003651
3652 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003653 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003654 return false;
3655}
3656
Toma Tabacu1a108322015-06-17 13:20:24 +00003657bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003658 MCStreamer &Out,
3659 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003660 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003661 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003662 unsigned PseudoOpcode = Inst.getOpcode();
3663 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003664 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003665 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3666
3667 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003668 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003669
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003670 unsigned TrgReg;
3671 if (TrgOp.isReg())
3672 TrgReg = TrgOp.getReg();
3673 else if (TrgOp.isImm()) {
3674 warnIfNoMacro(IDLoc);
3675 EmittedNoMacroWarning = true;
3676
3677 TrgReg = getATReg(IDLoc);
3678 if (!TrgReg)
3679 return true;
3680
3681 switch(PseudoOpcode) {
3682 default:
3683 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3684 case Mips::BLTImmMacro:
3685 PseudoOpcode = Mips::BLT;
3686 break;
3687 case Mips::BLEImmMacro:
3688 PseudoOpcode = Mips::BLE;
3689 break;
3690 case Mips::BGEImmMacro:
3691 PseudoOpcode = Mips::BGE;
3692 break;
3693 case Mips::BGTImmMacro:
3694 PseudoOpcode = Mips::BGT;
3695 break;
3696 case Mips::BLTUImmMacro:
3697 PseudoOpcode = Mips::BLTU;
3698 break;
3699 case Mips::BLEUImmMacro:
3700 PseudoOpcode = Mips::BLEU;
3701 break;
3702 case Mips::BGEUImmMacro:
3703 PseudoOpcode = Mips::BGEU;
3704 break;
3705 case Mips::BGTUImmMacro:
3706 PseudoOpcode = Mips::BGTU;
3707 break;
3708 case Mips::BLTLImmMacro:
3709 PseudoOpcode = Mips::BLTL;
3710 break;
3711 case Mips::BLELImmMacro:
3712 PseudoOpcode = Mips::BLEL;
3713 break;
3714 case Mips::BGELImmMacro:
3715 PseudoOpcode = Mips::BGEL;
3716 break;
3717 case Mips::BGTLImmMacro:
3718 PseudoOpcode = Mips::BGTL;
3719 break;
3720 case Mips::BLTULImmMacro:
3721 PseudoOpcode = Mips::BLTUL;
3722 break;
3723 case Mips::BLEULImmMacro:
3724 PseudoOpcode = Mips::BLEUL;
3725 break;
3726 case Mips::BGEULImmMacro:
3727 PseudoOpcode = Mips::BGEUL;
3728 break;
3729 case Mips::BGTULImmMacro:
3730 PseudoOpcode = Mips::BGTUL;
3731 break;
3732 }
3733
3734 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003735 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003736 return true;
3737 }
3738
Toma Tabacu1a108322015-06-17 13:20:24 +00003739 switch (PseudoOpcode) {
3740 case Mips::BLT:
3741 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003742 case Mips::BLTL:
3743 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003744 AcceptsEquality = false;
3745 ReverseOrderSLT = false;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003746 IsUnsigned =
3747 ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003748 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003749 ZeroSrcOpcode = Mips::BGTZ;
3750 ZeroTrgOpcode = Mips::BLTZ;
3751 break;
3752 case Mips::BLE:
3753 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003754 case Mips::BLEL:
3755 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003756 AcceptsEquality = true;
3757 ReverseOrderSLT = true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003758 IsUnsigned =
3759 ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003760 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003761 ZeroSrcOpcode = Mips::BGEZ;
3762 ZeroTrgOpcode = Mips::BLEZ;
3763 break;
3764 case Mips::BGE:
3765 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003766 case Mips::BGEL:
3767 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003768 AcceptsEquality = true;
3769 ReverseOrderSLT = false;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003770 IsUnsigned =
3771 ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003772 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003773 ZeroSrcOpcode = Mips::BLEZ;
3774 ZeroTrgOpcode = Mips::BGEZ;
3775 break;
3776 case Mips::BGT:
3777 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003778 case Mips::BGTL:
3779 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003780 AcceptsEquality = false;
3781 ReverseOrderSLT = true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003782 IsUnsigned =
3783 ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003784 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003785 ZeroSrcOpcode = Mips::BLTZ;
3786 ZeroTrgOpcode = Mips::BGTZ;
3787 break;
3788 default:
3789 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3790 }
3791
Toma Tabacu1a108322015-06-17 13:20:24 +00003792 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3793 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3794 if (IsSrcRegZero && IsTrgRegZero) {
3795 // FIXME: All of these Opcode-specific if's are needed for compatibility
3796 // with GAS' behaviour. However, they may not generate the most efficient
3797 // code in some circumstances.
3798 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003799 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3800 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003801 return false;
3802 }
3803 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003804 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3805 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003806 Warning(IDLoc, "branch is always taken");
3807 return false;
3808 }
3809 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003810 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3811 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003812 Warning(IDLoc, "branch is always taken");
3813 return false;
3814 }
3815 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003816 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3817 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003818 return false;
3819 }
3820 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003821 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3822 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003823 return false;
3824 }
3825 if (AcceptsEquality) {
3826 // If both registers are $0 and the pseudo-branch accepts equality, it
3827 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003828 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3829 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003830 Warning(IDLoc, "branch is always taken");
3831 return false;
3832 }
3833 // If both registers are $0 and the pseudo-branch does not accept
3834 // equality, it will never be taken, so we don't have to emit anything.
3835 return false;
3836 }
3837 if (IsSrcRegZero || IsTrgRegZero) {
3838 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3839 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3840 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3841 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3842 // the pseudo-branch will never be taken, so we don't emit anything.
3843 // This only applies to unsigned pseudo-branches.
3844 return false;
3845 }
3846 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3847 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3848 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3849 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3850 // the pseudo-branch will always be taken, so we emit an unconditional
3851 // branch.
3852 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003853 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3854 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003855 Warning(IDLoc, "branch is always taken");
3856 return false;
3857 }
3858 if (IsUnsigned) {
3859 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3860 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3861 // the pseudo-branch will be taken only when the non-zero register is
3862 // different from 0, so we emit a BNEZ.
3863 //
3864 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3865 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3866 // the pseudo-branch will be taken only when the non-zero register is
3867 // equal to 0, so we emit a BEQZ.
3868 //
3869 // Because only BLEU and BGEU branch on equality, we can use the
3870 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003871 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3872 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3873 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003874 return false;
3875 }
3876 // If we have a signed pseudo-branch and one of the registers is $0,
3877 // we can use an appropriate compare-to-zero branch. We select which one
3878 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003879 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3880 IsSrcRegZero ? TrgReg : SrcReg,
3881 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003882 return false;
3883 }
3884
3885 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3886 // expansions. If it is not available, we return.
3887 unsigned ATRegNum = getATReg(IDLoc);
3888 if (!ATRegNum)
3889 return true;
3890
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003891 if (!EmittedNoMacroWarning)
3892 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003893
3894 // SLT fits well with 2 of our 4 pseudo-branches:
3895 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3896 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3897 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3898 // This is accomplished by using a BNEZ with the result of the SLT.
3899 //
3900 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
Hiroshi Inoue7f9f92f2018-02-22 07:48:29 +00003901 // and BLE with BGT), so we change the BNEZ into a BEQZ.
Toma Tabacu1a108322015-06-17 13:20:24 +00003902 // Because only BGE and BLE branch on equality, we can use the
3903 // AcceptsEquality variable to decide when to emit the BEQZ.
3904 // Note that the order of the SLT arguments doesn't change between
3905 // opposites.
3906 //
3907 // The same applies to the unsigned variants, except that SLTu is used
3908 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003909 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3910 ReverseOrderSLT ? TrgReg : SrcReg,
3911 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003912
Daniel Sandersa736b372016-04-29 13:33:12 +00003913 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3914 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3915 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3916 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003917 return false;
3918}
3919
Simon Dardis509da1a2017-02-13 16:06:48 +00003920// Expand a integer division macro.
3921//
3922// Notably we don't have to emit a warning when encountering $rt as the $zero
3923// register, or 0 as an immediate. processInstruction() has already done that.
3924//
3925// The destination register can only be $zero when expanding (S)DivIMacro or
3926// D(S)DivMacro.
3927
Stefan Maksimovic0a239982018-07-09 13:06:44 +00003928bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3929 const MCSubtargetInfo *STI, const bool IsMips64,
3930 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003931 MipsTargetStreamer &TOut = getTargetStreamer();
3932
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003933 warnIfNoMacro(IDLoc);
3934
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003935 const MCOperand &RdRegOp = Inst.getOperand(0);
3936 assert(RdRegOp.isReg() && "expected register operand kind");
3937 unsigned RdReg = RdRegOp.getReg();
3938
3939 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003940 assert(RsRegOp.isReg() && "expected register operand kind");
3941 unsigned RsReg = RsRegOp.getReg();
3942
Simon Dardis12850ee2017-01-31 10:49:24 +00003943 unsigned RtReg;
3944 int64_t ImmValue;
3945
3946 const MCOperand &RtOp = Inst.getOperand(2);
3947 assert((RtOp.isReg() || RtOp.isImm()) &&
3948 "expected register or immediate operand kind");
3949 if (RtOp.isReg())
3950 RtReg = RtOp.getReg();
3951 else
3952 ImmValue = RtOp.getImm();
3953
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003954 unsigned DivOp;
3955 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003956 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003957
3958 if (IsMips64) {
3959 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3960 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003961 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003962 } else {
3963 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3964 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003965 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003966 }
3967
3968 bool UseTraps = useTraps();
3969
Stefan Maksimovic0a239982018-07-09 13:06:44 +00003970 unsigned Opcode = Inst.getOpcode();
3971 bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro ||
3972 Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro ||
3973 Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro ||
3974 Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro;
3975
3976 bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro ||
3977 Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro ||
3978 Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro ||
3979 Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro;
3980
Simon Dardis12850ee2017-01-31 10:49:24 +00003981 if (RtOp.isImm()) {
3982 unsigned ATReg = getATReg(IDLoc);
3983 if (!ATReg)
3984 return true;
3985
3986 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003987 if (UseTraps)
3988 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3989 else
3990 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3991 return false;
3992 }
3993
Stefan Maksimovic0a239982018-07-09 13:06:44 +00003994 if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1)))) {
3995 TOut.emitRRR(Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI);
3996 return false;
3997 } else if (isDiv && ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003998 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003999 return false;
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004000 } else if (isDiv && Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004001 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00004002 return false;
4003 } else {
4004 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
4005 false, Inst.getLoc(), Out, STI))
4006 return true;
4007 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004008 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00004009 return false;
4010 }
4011 return true;
4012 }
4013
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004014 // If the macro expansion of (d)div(u) or (d)rem(u) would always trap or
4015 // break, insert the trap/break and exit. This gives a different result to
4016 // GAS. GAS has an inconsistency/missed optimization in that not all cases
4017 // are handled equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004018 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004019 if (UseTraps) {
4020 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004021 return false;
4022 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004023 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4024 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004025 }
4026
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004027 // (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does
4028 // not expand to macro sequence.
4029 if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) {
4030 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
4031 return false;
4032 }
4033
Simon Dardis509da1a2017-02-13 16:06:48 +00004034 // Temporary label for first branch traget
4035 MCContext &Context = TOut.getStreamer().getContext();
4036 MCSymbol *BrTarget;
4037 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004038
4039 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004040 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004041 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004042 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004043 BrTarget = Context.createTempSymbol();
4044 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4045 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004046 }
4047
Daniel Sandersa736b372016-04-29 13:33:12 +00004048 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004049
4050 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004051 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004052
4053 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004054 if (!UseTraps)
4055 TOut.getStreamer().EmitLabel(BrTarget);
4056
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004057 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004058 return false;
4059 }
4060
4061 unsigned ATReg = getATReg(IDLoc);
4062 if (!ATReg)
4063 return true;
4064
Simon Dardis509da1a2017-02-13 16:06:48 +00004065 if (!UseTraps)
4066 TOut.getStreamer().EmitLabel(BrTarget);
4067
Daniel Sandersa736b372016-04-29 13:33:12 +00004068 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004069
4070 // Temporary label for the second branch target.
4071 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4072 MCOperand LabelOpEnd =
4073 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4074
4075 // Branch to the mflo instruction.
4076 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4077
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004078 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004079 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004080 TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004081 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004082 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004083 }
4084
4085 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004086 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004087 else {
4088 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004089 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004090 TOut.emitNop(IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004091 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004092 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004093
4094 TOut.getStreamer().EmitLabel(BrTargetEnd);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004095 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004096 return false;
4097}
4098
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004099bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004100 SMLoc IDLoc, MCStreamer &Out,
4101 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004102 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004103
4104 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4105 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4106 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4107
4108 unsigned FirstReg = Inst.getOperand(0).getReg();
4109 unsigned SecondReg = Inst.getOperand(1).getReg();
4110 unsigned ThirdReg = Inst.getOperand(2).getReg();
4111
4112 if (hasMips1() && !hasMips2()) {
4113 unsigned ATReg = getATReg(IDLoc);
4114 if (!ATReg)
4115 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004116 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4117 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4118 TOut.emitNop(IDLoc, STI);
4119 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4120 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4121 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4122 TOut.emitNop(IDLoc, STI);
4123 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4124 : Mips::CVT_W_S,
4125 FirstReg, SecondReg, IDLoc, STI);
4126 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4127 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004128 return false;
4129 }
4130
Daniel Sandersa736b372016-04-29 13:33:12 +00004131 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4132 : Mips::TRUNC_W_S,
4133 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004134
4135 return false;
4136}
4137
Daniel Sanders6394ee52015-10-15 14:52:58 +00004138bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004139 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004140 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004141 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004142 }
4143
Toma Tabacud88d79c2015-06-23 14:39:42 +00004144 const MCOperand &DstRegOp = Inst.getOperand(0);
4145 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004146 const MCOperand &SrcRegOp = Inst.getOperand(1);
4147 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004148 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4149 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4150
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004151 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004152 unsigned DstReg = DstRegOp.getReg();
4153 unsigned SrcReg = SrcRegOp.getReg();
4154 int64_t OffsetValue = OffsetImmOp.getImm();
4155
4156 // NOTE: We always need AT for ULHU, as it is always used as the source
4157 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004158 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004159 unsigned ATReg = getATReg(IDLoc);
4160 if (!ATReg)
4161 return true;
4162
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004163 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4164 if (IsLargeOffset) {
4165 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4166 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004167 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004168 }
4169
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004170 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4171 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4172 if (isLittle())
4173 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004174
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004175 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4176 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004177
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004178 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4179 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004180
Daniel Sandersa736b372016-04-29 13:33:12 +00004181 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004182 FirstOffset, IDLoc, STI);
4183 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004184 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004185 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004186
4187 return false;
4188}
4189
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004190bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004191 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004192 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004193 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004194 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004195
4196 const MCOperand &DstRegOp = Inst.getOperand(0);
4197 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004198 const MCOperand &SrcRegOp = Inst.getOperand(1);
4199 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004200 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4201 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4202
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004203 MipsTargetStreamer &TOut = getTargetStreamer();
4204 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004205 unsigned SrcReg = SrcRegOp.getReg();
4206 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004207
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004208 warnIfNoMacro(IDLoc);
4209 unsigned ATReg = getATReg(IDLoc);
4210 if (!ATReg)
4211 return true;
4212
4213 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4214 if (IsLargeOffset) {
4215 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4216 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004217 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004218 }
4219
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004220 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4221 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4222 if (isLittle())
4223 std::swap(FirstOffset, SecondOffset);
4224
4225 if (IsLargeOffset) {
4226 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4227 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4228 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4229 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4230 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4231 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004232 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004233 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4234 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4235 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004236 }
4237
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004238 return false;
4239}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004240
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004241bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4242 const MCSubtargetInfo *STI) {
4243 if (hasMips32r6() || hasMips64r6()) {
4244 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4245 }
4246
4247 const MCOperand &DstRegOp = Inst.getOperand(0);
4248 assert(DstRegOp.isReg() && "expected register operand kind");
4249 const MCOperand &SrcRegOp = Inst.getOperand(1);
4250 assert(SrcRegOp.isReg() && "expected register operand kind");
4251 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4252 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4253
4254 MipsTargetStreamer &TOut = getTargetStreamer();
4255 unsigned DstReg = DstRegOp.getReg();
4256 unsigned SrcReg = SrcRegOp.getReg();
4257 int64_t OffsetValue = OffsetImmOp.getImm();
4258
4259 // Compute left/right load/store offsets.
4260 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4261 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4262 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4263 if (isLittle())
4264 std::swap(LxlOffset, LxrOffset);
4265
4266 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4267 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4268 unsigned TmpReg = SrcReg;
4269 if (IsLargeOffset || DoMove) {
4270 warnIfNoMacro(IDLoc);
4271 TmpReg = getATReg(IDLoc);
4272 if (!TmpReg)
4273 return true;
4274 }
4275
4276 if (IsLargeOffset) {
4277 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4278 IDLoc, Out, STI))
4279 return true;
4280 }
4281
4282 if (DoMove)
4283 std::swap(DstReg, TmpReg);
4284
4285 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4286 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4287 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4288 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4289
4290 if (DoMove)
4291 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004292
4293 return false;
4294}
4295
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004296bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004297 MCStreamer &Out,
4298 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004299 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004300
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004301 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4302 assert(Inst.getOperand(0).isReg() &&
4303 Inst.getOperand(1).isReg() &&
4304 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004305
4306 unsigned ATReg = Mips::NoRegister;
4307 unsigned FinalDstReg = Mips::NoRegister;
4308 unsigned DstReg = Inst.getOperand(0).getReg();
4309 unsigned SrcReg = Inst.getOperand(1).getReg();
4310 int64_t ImmValue = Inst.getOperand(2).getImm();
4311
Simon Dardisaa208812017-02-24 14:34:32 +00004312 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004313
4314 unsigned FinalOpcode = Inst.getOpcode();
4315
4316 if (DstReg == SrcReg) {
4317 ATReg = getATReg(Inst.getLoc());
4318 if (!ATReg)
4319 return true;
4320 FinalDstReg = DstReg;
4321 DstReg = ATReg;
4322 }
4323
Simon Atanasyan478220f2018-05-24 07:36:00 +00004324 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false,
4325 Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004326 switch (FinalOpcode) {
4327 default:
4328 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004329 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004330 FinalOpcode = Mips::ADD;
4331 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004332 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004333 FinalOpcode = Mips::ADDu;
4334 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004335 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004336 FinalOpcode = Mips::AND;
4337 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004338 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004339 FinalOpcode = Mips::NOR;
4340 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004341 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004342 FinalOpcode = Mips::OR;
4343 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004344 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004345 FinalOpcode = Mips::SLT;
4346 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004347 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004348 FinalOpcode = Mips::SLTu;
4349 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004350 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004351 FinalOpcode = Mips::XOR;
4352 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004353 case Mips::ADDi_MM:
4354 FinalOpcode = Mips::ADD_MM;
4355 break;
4356 case Mips::ADDiu_MM:
4357 FinalOpcode = Mips::ADDu_MM;
4358 break;
4359 case Mips::ANDi_MM:
4360 FinalOpcode = Mips::AND_MM;
4361 break;
4362 case Mips::ORi_MM:
4363 FinalOpcode = Mips::OR_MM;
4364 break;
4365 case Mips::SLTi_MM:
4366 FinalOpcode = Mips::SLT_MM;
4367 break;
4368 case Mips::SLTiu_MM:
4369 FinalOpcode = Mips::SLTu_MM;
4370 break;
4371 case Mips::XORi_MM:
4372 FinalOpcode = Mips::XOR_MM;
4373 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004374 case Mips::ANDi64:
4375 FinalOpcode = Mips::AND64;
4376 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004377 case Mips::NORImm64:
4378 FinalOpcode = Mips::NOR64;
4379 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004380 case Mips::ORi64:
4381 FinalOpcode = Mips::OR64;
4382 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004383 case Mips::SLTImm64:
4384 FinalOpcode = Mips::SLT64;
4385 break;
4386 case Mips::SLTUImm64:
4387 FinalOpcode = Mips::SLTu64;
4388 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004389 case Mips::XORi64:
4390 FinalOpcode = Mips::XOR64;
4391 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004392 }
4393
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004394 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004395 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004396 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004397 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004398 return false;
4399 }
4400 return true;
4401}
4402
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004403bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4404 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004405 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004406 unsigned ATReg = Mips::NoRegister;
4407 unsigned DReg = Inst.getOperand(0).getReg();
4408 unsigned SReg = Inst.getOperand(1).getReg();
4409 unsigned TReg = Inst.getOperand(2).getReg();
4410 unsigned TmpReg = DReg;
4411
4412 unsigned FirstShift = Mips::NOP;
4413 unsigned SecondShift = Mips::NOP;
4414
4415 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004416 if (DReg == SReg) {
4417 TmpReg = getATReg(Inst.getLoc());
4418 if (!TmpReg)
4419 return true;
4420 }
4421
4422 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004423 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4424 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004425 return false;
4426 }
4427
4428 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004429 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004430 return false;
4431 }
4432
4433 return true;
4434 }
4435
4436 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004437 switch (Inst.getOpcode()) {
4438 default:
4439 llvm_unreachable("unexpected instruction opcode");
4440 case Mips::ROL:
4441 FirstShift = Mips::SRLV;
4442 SecondShift = Mips::SLLV;
4443 break;
4444 case Mips::ROR:
4445 FirstShift = Mips::SLLV;
4446 SecondShift = Mips::SRLV;
4447 break;
4448 }
4449
4450 ATReg = getATReg(Inst.getLoc());
4451 if (!ATReg)
4452 return true;
4453
Daniel Sandersa736b372016-04-29 13:33:12 +00004454 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4455 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4456 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4457 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004458
4459 return false;
4460 }
4461
4462 return true;
4463}
4464
4465bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004466 MCStreamer &Out,
4467 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004468 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004469 unsigned ATReg = Mips::NoRegister;
4470 unsigned DReg = Inst.getOperand(0).getReg();
4471 unsigned SReg = Inst.getOperand(1).getReg();
4472 int64_t ImmValue = Inst.getOperand(2).getImm();
4473
4474 unsigned FirstShift = Mips::NOP;
4475 unsigned SecondShift = Mips::NOP;
4476
4477 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004478 if (Inst.getOpcode() == Mips::ROLImm) {
4479 uint64_t MaxShift = 32;
4480 uint64_t ShiftValue = ImmValue;
4481 if (ImmValue != 0)
4482 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004483 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004484 return false;
4485 }
4486
4487 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004488 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004489 return false;
4490 }
4491
4492 return true;
4493 }
4494
4495 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004496 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004497 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004498 return false;
4499 }
4500
4501 switch (Inst.getOpcode()) {
4502 default:
4503 llvm_unreachable("unexpected instruction opcode");
4504 case Mips::ROLImm:
4505 FirstShift = Mips::SLL;
4506 SecondShift = Mips::SRL;
4507 break;
4508 case Mips::RORImm:
4509 FirstShift = Mips::SRL;
4510 SecondShift = Mips::SLL;
4511 break;
4512 }
4513
4514 ATReg = getATReg(Inst.getLoc());
4515 if (!ATReg)
4516 return true;
4517
Daniel Sandersa736b372016-04-29 13:33:12 +00004518 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4519 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4520 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004521
4522 return false;
4523 }
4524
4525 return true;
4526}
4527
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004528bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4529 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004530 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004531 unsigned ATReg = Mips::NoRegister;
4532 unsigned DReg = Inst.getOperand(0).getReg();
4533 unsigned SReg = Inst.getOperand(1).getReg();
4534 unsigned TReg = Inst.getOperand(2).getReg();
4535 unsigned TmpReg = DReg;
4536
4537 unsigned FirstShift = Mips::NOP;
4538 unsigned SecondShift = Mips::NOP;
4539
4540 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004541 if (TmpReg == SReg) {
4542 TmpReg = getATReg(Inst.getLoc());
4543 if (!TmpReg)
4544 return true;
4545 }
4546
4547 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004548 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4549 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004550 return false;
4551 }
4552
4553 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004554 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004555 return false;
4556 }
4557
4558 return true;
4559 }
4560
4561 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004562 switch (Inst.getOpcode()) {
4563 default:
4564 llvm_unreachable("unexpected instruction opcode");
4565 case Mips::DROL:
4566 FirstShift = Mips::DSRLV;
4567 SecondShift = Mips::DSLLV;
4568 break;
4569 case Mips::DROR:
4570 FirstShift = Mips::DSLLV;
4571 SecondShift = Mips::DSRLV;
4572 break;
4573 }
4574
4575 ATReg = getATReg(Inst.getLoc());
4576 if (!ATReg)
4577 return true;
4578
Daniel Sandersa736b372016-04-29 13:33:12 +00004579 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4580 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4581 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4582 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004583
4584 return false;
4585 }
4586
4587 return true;
4588}
4589
4590bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004591 MCStreamer &Out,
4592 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004593 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004594 unsigned ATReg = Mips::NoRegister;
4595 unsigned DReg = Inst.getOperand(0).getReg();
4596 unsigned SReg = Inst.getOperand(1).getReg();
4597 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4598
4599 unsigned FirstShift = Mips::NOP;
4600 unsigned SecondShift = Mips::NOP;
4601
4602 MCInst TmpInst;
4603
4604 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004605 unsigned FinalOpcode = Mips::NOP;
4606 if (ImmValue == 0)
4607 FinalOpcode = Mips::DROTR;
4608 else if (ImmValue % 32 == 0)
4609 FinalOpcode = Mips::DROTR32;
4610 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4611 if (Inst.getOpcode() == Mips::DROLImm)
4612 FinalOpcode = Mips::DROTR32;
4613 else
4614 FinalOpcode = Mips::DROTR;
4615 } else if (ImmValue >= 33) {
4616 if (Inst.getOpcode() == Mips::DROLImm)
4617 FinalOpcode = Mips::DROTR;
4618 else
4619 FinalOpcode = Mips::DROTR32;
4620 }
4621
4622 uint64_t ShiftValue = ImmValue % 32;
4623 if (Inst.getOpcode() == Mips::DROLImm)
4624 ShiftValue = (32 - ImmValue % 32) % 32;
4625
Daniel Sandersa736b372016-04-29 13:33:12 +00004626 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004627
4628 return false;
4629 }
4630
4631 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004632 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004633 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004634 return false;
4635 }
4636
4637 switch (Inst.getOpcode()) {
4638 default:
4639 llvm_unreachable("unexpected instruction opcode");
4640 case Mips::DROLImm:
4641 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4642 FirstShift = Mips::DSLL;
4643 SecondShift = Mips::DSRL32;
4644 }
4645 if (ImmValue == 32) {
4646 FirstShift = Mips::DSLL32;
4647 SecondShift = Mips::DSRL32;
4648 }
4649 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4650 FirstShift = Mips::DSLL32;
4651 SecondShift = Mips::DSRL;
4652 }
4653 break;
4654 case Mips::DRORImm:
4655 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4656 FirstShift = Mips::DSRL;
4657 SecondShift = Mips::DSLL32;
4658 }
4659 if (ImmValue == 32) {
4660 FirstShift = Mips::DSRL32;
4661 SecondShift = Mips::DSLL32;
4662 }
4663 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4664 FirstShift = Mips::DSRL32;
4665 SecondShift = Mips::DSLL;
4666 }
4667 break;
4668 }
4669
4670 ATReg = getATReg(Inst.getLoc());
4671 if (!ATReg)
4672 return true;
4673
Daniel Sandersa736b372016-04-29 13:33:12 +00004674 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4675 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4676 Inst.getLoc(), STI);
4677 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004678
4679 return false;
4680 }
4681
4682 return true;
4683}
4684
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004685bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4686 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004687 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004688 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4689 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4690
Daniel Sandersa736b372016-04-29 13:33:12 +00004691 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004692 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004693 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004694 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004695 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4696 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004697
4698 return false;
4699}
4700
Simon Dardis3c82a642017-02-08 16:25:05 +00004701bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4702 const MCSubtargetInfo *STI) {
4703 MipsTargetStreamer &TOut = getTargetStreamer();
4704 unsigned ATReg = Mips::NoRegister;
4705 unsigned DstReg = Inst.getOperand(0).getReg();
4706 unsigned SrcReg = Inst.getOperand(1).getReg();
4707 int32_t ImmValue = Inst.getOperand(2).getImm();
4708
4709 ATReg = getATReg(IDLoc);
4710 if (!ATReg)
4711 return true;
4712
Simon Atanasyan478220f2018-05-24 07:36:00 +00004713 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out,
4714 STI);
Simon Dardis3c82a642017-02-08 16:25:05 +00004715
4716 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4717 SrcReg, ATReg, IDLoc, STI);
4718
4719 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4720
4721 return false;
4722}
4723
4724bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4725 const MCSubtargetInfo *STI) {
4726 MipsTargetStreamer &TOut = getTargetStreamer();
4727 unsigned ATReg = Mips::NoRegister;
4728 unsigned DstReg = Inst.getOperand(0).getReg();
4729 unsigned SrcReg = Inst.getOperand(1).getReg();
4730 unsigned TmpReg = Inst.getOperand(2).getReg();
4731
4732 ATReg = getATReg(Inst.getLoc());
4733 if (!ATReg)
4734 return true;
4735
4736 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4737 SrcReg, TmpReg, IDLoc, STI);
4738
4739 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4740
4741 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4742 DstReg, DstReg, 0x1F, IDLoc, STI);
4743
4744 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4745
4746 if (useTraps()) {
4747 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4748 } else {
4749 MCContext & Context = TOut.getStreamer().getContext();
4750 MCSymbol * BrTarget = Context.createTempSymbol();
4751 MCOperand LabelOp =
4752 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4753
4754 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4755 if (AssemblerOptions.back()->isReorder())
4756 TOut.emitNop(IDLoc, STI);
4757 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4758
4759 TOut.getStreamer().EmitLabel(BrTarget);
4760 }
4761 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4762
4763 return false;
4764}
4765
4766bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4767 const MCSubtargetInfo *STI) {
4768 MipsTargetStreamer &TOut = getTargetStreamer();
4769 unsigned ATReg = Mips::NoRegister;
4770 unsigned DstReg = Inst.getOperand(0).getReg();
4771 unsigned SrcReg = Inst.getOperand(1).getReg();
4772 unsigned TmpReg = Inst.getOperand(2).getReg();
4773
4774 ATReg = getATReg(IDLoc);
4775 if (!ATReg)
4776 return true;
4777
4778 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4779 SrcReg, TmpReg, IDLoc, STI);
4780
4781 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4782 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4783 if (useTraps()) {
4784 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4785 } else {
4786 MCContext & Context = TOut.getStreamer().getContext();
4787 MCSymbol * BrTarget = Context.createTempSymbol();
4788 MCOperand LabelOp =
4789 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4790
4791 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4792 if (AssemblerOptions.back()->isReorder())
4793 TOut.emitNop(IDLoc, STI);
4794 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4795
4796 TOut.getStreamer().EmitLabel(BrTarget);
4797 }
4798
4799 return false;
4800}
4801
4802bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4803 const MCSubtargetInfo *STI) {
4804 MipsTargetStreamer &TOut = getTargetStreamer();
4805 unsigned DstReg = Inst.getOperand(0).getReg();
4806 unsigned SrcReg = Inst.getOperand(1).getReg();
4807 unsigned TmpReg = Inst.getOperand(2).getReg();
4808
4809 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4810 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4811
4812 return false;
4813}
4814
Simon Dardisaff4d142016-10-18 14:28:00 +00004815// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4816// lw $<reg+1>>, offset+4($reg2)'
4817// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4818// sw $<reg+1>>, offset+4($reg2)'
4819// for O32.
4820bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4821 MCStreamer &Out,
4822 const MCSubtargetInfo *STI,
4823 bool IsLoad) {
4824 if (!isABI_O32())
4825 return true;
4826
4827 warnIfNoMacro(IDLoc);
4828
4829 MipsTargetStreamer &TOut = getTargetStreamer();
4830 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4831 unsigned FirstReg = Inst.getOperand(0).getReg();
4832 unsigned SecondReg = nextReg(FirstReg);
4833 unsigned BaseReg = Inst.getOperand(1).getReg();
4834 if (!SecondReg)
4835 return true;
4836
4837 warnIfRegIndexIsAT(FirstReg, IDLoc);
4838
4839 assert(Inst.getOperand(2).isImm() &&
4840 "Offset for load macro is not immediate!");
4841
4842 MCOperand &FirstOffset = Inst.getOperand(2);
4843 signed NextOffset = FirstOffset.getImm() + 4;
4844 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4845
4846 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4847 return true;
4848
4849 // For loads, clobber the base register with the second load instead of the
4850 // first if the BaseReg == FirstReg.
4851 if (FirstReg != BaseReg || !IsLoad) {
4852 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4853 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4854 } else {
4855 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4856 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4857 }
4858
4859 return false;
4860}
4861
Simon Dardis43115a12016-11-21 20:30:41 +00004862bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4863 const MCSubtargetInfo *STI) {
4864
4865 warnIfNoMacro(IDLoc);
4866 MipsTargetStreamer &TOut = getTargetStreamer();
4867
4868 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4869 Inst.getOperand(2).getReg() != Mips::ZERO) {
4870 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4871 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4872 IDLoc, STI);
4873 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4874 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4875 return false;
4876 }
4877
4878 unsigned Reg = 0;
4879 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4880 Reg = Inst.getOperand(2).getReg();
4881 } else {
4882 Reg = Inst.getOperand(1).getReg();
4883 }
4884 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4885 return false;
4886}
4887
4888bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4889 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004890 warnIfNoMacro(IDLoc);
4891 MipsTargetStreamer &TOut = getTargetStreamer();
4892
4893 unsigned Opc;
4894 int64_t Imm = Inst.getOperand(2).getImm();
4895 unsigned Reg = Inst.getOperand(1).getReg();
4896
4897 if (Imm == 0) {
4898 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4899 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4900 return false;
4901 } else {
4902
4903 if (Reg == Mips::ZERO) {
4904 Warning(IDLoc, "comparison is always false");
4905 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4906 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4907 return false;
4908 }
4909
4910 if (Imm > -0x8000 && Imm < 0) {
4911 Imm = -Imm;
4912 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4913 } else {
4914 Opc = Mips::XORi;
4915 }
4916 }
4917 if (!isUInt<16>(Imm)) {
4918 unsigned ATReg = getATReg(IDLoc);
4919 if (!ATReg)
4920 return true;
4921
4922 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4923 Out, STI))
4924 return true;
4925
4926 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4927 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4928 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4929 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4930 return false;
4931 }
4932
4933 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4934 Imm, IDLoc, STI);
4935 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4936 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4937 return false;
4938}
4939
Simon Dardisde5ed0c2017-11-14 22:26:42 +00004940// Map the DSP accumulator and control register to the corresponding gpr
4941// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
4942// do not map the DSP registers contigously to gpr registers.
4943static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
4944 switch (Inst.getOpcode()) {
4945 case Mips::MFTLO:
4946 case Mips::MTTLO:
4947 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4948 case Mips::AC0:
4949 return Mips::ZERO;
4950 case Mips::AC1:
4951 return Mips::A0;
4952 case Mips::AC2:
4953 return Mips::T0;
4954 case Mips::AC3:
4955 return Mips::T4;
4956 default:
4957 llvm_unreachable("Unknown register for 'mttr' alias!");
4958 }
4959 case Mips::MFTHI:
4960 case Mips::MTTHI:
4961 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4962 case Mips::AC0:
4963 return Mips::AT;
4964 case Mips::AC1:
4965 return Mips::A1;
4966 case Mips::AC2:
4967 return Mips::T1;
4968 case Mips::AC3:
4969 return Mips::T5;
4970 default:
4971 llvm_unreachable("Unknown register for 'mttr' alias!");
4972 }
4973 case Mips::MFTACX:
4974 case Mips::MTTACX:
4975 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4976 case Mips::AC0:
4977 return Mips::V0;
4978 case Mips::AC1:
4979 return Mips::A2;
4980 case Mips::AC2:
4981 return Mips::T2;
4982 case Mips::AC3:
4983 return Mips::T6;
4984 default:
4985 llvm_unreachable("Unknown register for 'mttr' alias!");
4986 }
4987 case Mips::MFTDSP:
4988 case Mips::MTTDSP:
4989 return Mips::S0;
4990 default:
4991 llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
4992 }
4993}
4994
4995// Map the floating point register operand to the corresponding register
4996// operand.
4997static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
4998 switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
4999 case Mips::F0: return Mips::ZERO;
5000 case Mips::F1: return Mips::AT;
5001 case Mips::F2: return Mips::V0;
5002 case Mips::F3: return Mips::V1;
5003 case Mips::F4: return Mips::A0;
5004 case Mips::F5: return Mips::A1;
5005 case Mips::F6: return Mips::A2;
5006 case Mips::F7: return Mips::A3;
5007 case Mips::F8: return Mips::T0;
5008 case Mips::F9: return Mips::T1;
5009 case Mips::F10: return Mips::T2;
5010 case Mips::F11: return Mips::T3;
5011 case Mips::F12: return Mips::T4;
5012 case Mips::F13: return Mips::T5;
5013 case Mips::F14: return Mips::T6;
5014 case Mips::F15: return Mips::T7;
5015 case Mips::F16: return Mips::S0;
5016 case Mips::F17: return Mips::S1;
5017 case Mips::F18: return Mips::S2;
5018 case Mips::F19: return Mips::S3;
5019 case Mips::F20: return Mips::S4;
5020 case Mips::F21: return Mips::S5;
5021 case Mips::F22: return Mips::S6;
5022 case Mips::F23: return Mips::S7;
5023 case Mips::F24: return Mips::T8;
5024 case Mips::F25: return Mips::T9;
5025 case Mips::F26: return Mips::K0;
5026 case Mips::F27: return Mips::K1;
5027 case Mips::F28: return Mips::GP;
5028 case Mips::F29: return Mips::SP;
5029 case Mips::F30: return Mips::FP;
5030 case Mips::F31: return Mips::RA;
5031 default: llvm_unreachable("Unknown register for mttc1 alias!");
5032 }
5033}
5034
5035// Map the coprocessor operand the corresponding gpr register operand.
5036static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
5037 switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
5038 case Mips::COP00: return Mips::ZERO;
5039 case Mips::COP01: return Mips::AT;
5040 case Mips::COP02: return Mips::V0;
5041 case Mips::COP03: return Mips::V1;
5042 case Mips::COP04: return Mips::A0;
5043 case Mips::COP05: return Mips::A1;
5044 case Mips::COP06: return Mips::A2;
5045 case Mips::COP07: return Mips::A3;
5046 case Mips::COP08: return Mips::T0;
5047 case Mips::COP09: return Mips::T1;
5048 case Mips::COP010: return Mips::T2;
5049 case Mips::COP011: return Mips::T3;
5050 case Mips::COP012: return Mips::T4;
5051 case Mips::COP013: return Mips::T5;
5052 case Mips::COP014: return Mips::T6;
5053 case Mips::COP015: return Mips::T7;
5054 case Mips::COP016: return Mips::S0;
5055 case Mips::COP017: return Mips::S1;
5056 case Mips::COP018: return Mips::S2;
5057 case Mips::COP019: return Mips::S3;
5058 case Mips::COP020: return Mips::S4;
5059 case Mips::COP021: return Mips::S5;
5060 case Mips::COP022: return Mips::S6;
5061 case Mips::COP023: return Mips::S7;
5062 case Mips::COP024: return Mips::T8;
5063 case Mips::COP025: return Mips::T9;
5064 case Mips::COP026: return Mips::K0;
5065 case Mips::COP027: return Mips::K1;
5066 case Mips::COP028: return Mips::GP;
5067 case Mips::COP029: return Mips::SP;
5068 case Mips::COP030: return Mips::FP;
5069 case Mips::COP031: return Mips::RA;
5070 default: llvm_unreachable("Unknown register for mttc0 alias!");
5071 }
5072}
5073
5074/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
5075/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
5076bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5077 const MCSubtargetInfo *STI) {
5078 MipsTargetStreamer &TOut = getTargetStreamer();
5079 unsigned rd = 0;
5080 unsigned u = 1;
5081 unsigned sel = 0;
5082 unsigned h = 0;
5083 bool IsMFTR = false;
5084 switch (Inst.getOpcode()) {
5085 case Mips::MFTC0:
5086 IsMFTR = true;
5087 LLVM_FALLTHROUGH;
5088 case Mips::MTTC0:
5089 u = 0;
5090 rd = getRegisterForMxtrC0(Inst, IsMFTR);
5091 sel = Inst.getOperand(2).getImm();
5092 break;
5093 case Mips::MFTGPR:
5094 IsMFTR = true;
5095 LLVM_FALLTHROUGH;
5096 case Mips::MTTGPR:
5097 rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
5098 break;
5099 case Mips::MFTLO:
5100 case Mips::MFTHI:
5101 case Mips::MFTACX:
5102 case Mips::MFTDSP:
5103 IsMFTR = true;
5104 LLVM_FALLTHROUGH;
5105 case Mips::MTTLO:
5106 case Mips::MTTHI:
5107 case Mips::MTTACX:
5108 case Mips::MTTDSP:
5109 rd = getRegisterForMxtrDSP(Inst, IsMFTR);
5110 sel = 1;
5111 break;
5112 case Mips::MFTHC1:
5113 h = 1;
5114 LLVM_FALLTHROUGH;
5115 case Mips::MFTC1:
5116 IsMFTR = true;
5117 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5118 sel = 2;
5119 break;
5120 case Mips::MTTHC1:
5121 h = 1;
5122 LLVM_FALLTHROUGH;
5123 case Mips::MTTC1:
5124 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5125 sel = 2;
5126 break;
5127 case Mips::CFTC1:
5128 IsMFTR = true;
5129 LLVM_FALLTHROUGH;
5130 case Mips::CTTC1:
5131 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5132 sel = 3;
5133 break;
5134 }
5135 unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
5136 unsigned Op1 =
5137 IsMFTR ? rd
5138 : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
5139 : Inst.getOperand(0).getReg());
5140
5141 TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
5142 STI);
5143 return false;
5144}
5145
Daniel Sandersc5537422016-07-27 13:49:44 +00005146unsigned
5147MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
5148 const OperandVector &Operands) {
5149 switch (Inst.getOpcode()) {
5150 default:
5151 return Match_Success;
5152 case Mips::DATI:
5153 case Mips::DAHI:
Daniel Sandersb23005e2016-07-28 15:59:06 +00005154 if (static_cast<MipsOperand &>(*Operands[1])
5155 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
5156 return Match_Success;
5157 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00005158 }
5159}
Simon Dardis730fdb72017-01-16 13:55:58 +00005160
Matheus Almeida595fcab2014-06-11 15:05:56 +00005161unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00005162 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00005163 // As described by the MIPSR6 spec, daui must not use the zero operand for
5164 // its source operand.
5165 case Mips::DAUI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00005166 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5167 Inst.getOperand(1).getReg() == Mips::ZERO_64)
5168 return Match_RequiresNoZeroRegister;
5169 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00005170 // As described by the Mips32r2 spec, the registers Rd and Rs for
5171 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00005172 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00005173 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00005174 case Mips::JALR_HB:
Simon Dardis7bc8ad52018-02-21 00:06:53 +00005175 case Mips::JALR_HB64:
Simon Dardisb60833c2016-05-31 17:34:42 +00005176 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00005177 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00005178 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5179 return Match_RequiresDifferentSrcAndDst;
5180 return Match_Success;
5181 case Mips::LWP_MM:
Simon Dardisb60833c2016-05-31 17:34:42 +00005182 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
5183 return Match_RequiresDifferentSrcAndDst;
5184 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00005185 case Mips::SYNC:
5186 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
5187 return Match_NonZeroOperandForSync;
5188 return Match_Success;
Simon Dardis52ae4f02018-03-07 11:39:48 +00005189 case Mips::MFC0:
5190 case Mips::MTC0:
5191 case Mips::MTC2:
5192 case Mips::MFC2:
5193 if (Inst.getOperand(2).getImm() != 0 && !hasMips32())
5194 return Match_NonZeroOperandForMTCX;
5195 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005196 // As described the MIPSR6 spec, the compact branches that compare registers
5197 // must:
5198 // a) Not use the zero register.
5199 // b) Not use the same register twice.
5200 // c) rs < rt for bnec, beqc.
5201 // NB: For this case, the encoding will swap the operands as their
5202 // ordering doesn't matter. GAS performs this transformation too.
5203 // Hence, that constraint does not have to be enforced.
5204 //
5205 // The compact branches that branch iff the signed addition of two registers
5206 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
5207 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005208 case Mips::BLEZC: case Mips::BLEZC_MMR6:
5209 case Mips::BGEZC: case Mips::BGEZC_MMR6:
5210 case Mips::BGTZC: case Mips::BGTZC_MMR6:
5211 case Mips::BLTZC: case Mips::BLTZC_MMR6:
5212 case Mips::BEQZC: case Mips::BEQZC_MMR6:
5213 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005214 case Mips::BLEZC64:
5215 case Mips::BGEZC64:
5216 case Mips::BGTZC64:
5217 case Mips::BLTZC64:
5218 case Mips::BEQZC64:
5219 case Mips::BNEZC64:
5220 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5221 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005222 return Match_RequiresNoZeroRegister;
5223 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005224 case Mips::BGEC: case Mips::BGEC_MMR6:
5225 case Mips::BLTC: case Mips::BLTC_MMR6:
5226 case Mips::BGEUC: case Mips::BGEUC_MMR6:
5227 case Mips::BLTUC: case Mips::BLTUC_MMR6:
5228 case Mips::BEQC: case Mips::BEQC_MMR6:
5229 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005230 case Mips::BGEC64:
5231 case Mips::BLTC64:
5232 case Mips::BGEUC64:
5233 case Mips::BLTUC64:
5234 case Mips::BEQC64:
5235 case Mips::BNEC64:
5236 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5237 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005238 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00005239 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5240 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005241 return Match_RequiresNoZeroRegister;
5242 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5243 return Match_RequiresDifferentOperands;
5244 return Match_Success;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005245 case Mips::DINS: {
Simon Dardis55e44672017-09-14 17:27:53 +00005246 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5247 "Operands must be immediates for dins!");
5248 const signed Pos = Inst.getOperand(2).getImm();
5249 const signed Size = Inst.getOperand(3).getImm();
5250 if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
5251 return Match_RequiresPosSizeRange0_32;
5252 return Match_Success;
5253 }
5254 case Mips::DINSM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005255 case Mips::DINSU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005256 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5257 "Operands must be immediates for dinsm/dinsu!");
5258 const signed Pos = Inst.getOperand(2).getImm();
5259 const signed Size = Inst.getOperand(3).getImm();
5260 if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
5261 return Match_RequiresPosSizeRange33_64;
5262 return Match_Success;
5263 }
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005264 case Mips::DEXT: {
Simon Dardis55e44672017-09-14 17:27:53 +00005265 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5266 "Operands must be immediates for DEXTM!");
5267 const signed Pos = Inst.getOperand(2).getImm();
5268 const signed Size = Inst.getOperand(3).getImm();
5269 if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
5270 return Match_RequiresPosSizeUImm6;
5271 return Match_Success;
5272 }
5273 case Mips::DEXTM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005274 case Mips::DEXTU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005275 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5276 "Operands must be immediates for dextm/dextu!");
5277 const signed Pos = Inst.getOperand(2).getImm();
5278 const signed Size = Inst.getOperand(3).getImm();
5279 if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
5280 return Match_RequiresPosSizeRange33_64;
5281 return Match_Success;
5282 }
Petar Jovanovic3408caf2018-03-14 14:13:31 +00005283 case Mips::CRC32B: case Mips::CRC32CB:
5284 case Mips::CRC32H: case Mips::CRC32CH:
5285 case Mips::CRC32W: case Mips::CRC32CW:
5286 case Mips::CRC32D: case Mips::CRC32CD:
5287 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())
5288 return Match_RequiresSameSrcAndDst;
5289 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005290 }
Simon Dardis730fdb72017-01-16 13:55:58 +00005291
5292 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
5293 if ((TSFlags & MipsII::HasFCCRegOperand) &&
5294 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
5295 return Match_NoFCCRegisterForCurrentISA;
5296
5297 return Match_Success;
5298
Matheus Almeida595fcab2014-06-11 15:05:56 +00005299}
5300
Daniel Sanders52da7af2015-11-06 12:11:03 +00005301static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
5302 uint64_t ErrorInfo) {
5303 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
5304 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
5305 if (ErrorLoc == SMLoc())
5306 return Loc;
5307 return ErrorLoc;
5308 }
5309 return Loc;
5310}
5311
David Blaikie960ea3f2014-06-08 16:18:35 +00005312bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5313 OperandVector &Operands,
5314 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005315 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005316 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005317 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005318 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005319 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005320
5321 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005322 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005323 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005324 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005325 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005326 case Match_MissingFeature:
5327 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5328 return true;
5329 case Match_InvalidOperand: {
5330 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005331 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005332 if (ErrorInfo >= Operands.size())
5333 return Error(IDLoc, "too few operands for instruction");
5334
Daniel Sanders52da7af2015-11-06 12:11:03 +00005335 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005336 if (ErrorLoc == SMLoc())
5337 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005338 }
5339
5340 return Error(ErrorLoc, "invalid operand for instruction");
5341 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005342 case Match_NonZeroOperandForSync:
Simon Atanasyan478220f2018-05-24 07:36:00 +00005343 return Error(IDLoc,
5344 "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Simon Dardis52ae4f02018-03-07 11:39:48 +00005345 case Match_NonZeroOperandForMTCX:
5346 return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005347 case Match_MnemonicFail:
5348 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005349 case Match_RequiresDifferentSrcAndDst:
5350 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005351 case Match_RequiresDifferentOperands:
5352 return Error(IDLoc, "registers must be different");
5353 case Match_RequiresNoZeroRegister:
5354 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005355 case Match_RequiresSameSrcAndDst:
5356 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005357 case Match_NoFCCRegisterForCurrentISA:
5358 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5359 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005360 case Match_Immz:
5361 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005362 case Match_UImm1_0:
5363 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5364 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005365 case Match_UImm2_0:
5366 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5367 "expected 2-bit unsigned immediate");
5368 case Match_UImm2_1:
5369 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5370 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005371 case Match_UImm3_0:
5372 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5373 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005374 case Match_UImm4_0:
5375 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5376 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005377 case Match_SImm4_0:
5378 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5379 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005380 case Match_UImm5_0:
5381 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5382 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005383 case Match_SImm5_0:
5384 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5385 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005386 case Match_UImm5_1:
5387 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5388 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005389 case Match_UImm5_32:
5390 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5391 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005392 case Match_UImm5_33:
5393 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5394 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005395 case Match_UImm5_0_Report_UImm6:
5396 // This is used on UImm5 operands that have a corresponding UImm5_32
5397 // operand to avoid confusing the user.
5398 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5399 "expected 6-bit unsigned immediate");
5400 case Match_UImm5_Lsl2:
5401 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5402 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005403 case Match_UImmRange2_64:
5404 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5405 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005406 case Match_UImm6_0:
5407 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5408 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005409 case Match_UImm6_Lsl2:
5410 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5411 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005412 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005413 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5414 "expected 6-bit signed immediate");
5415 case Match_UImm7_0:
5416 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5417 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005418 case Match_UImm7_N1:
5419 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5420 "expected immediate in range -1 .. 126");
5421 case Match_SImm7_Lsl2:
5422 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5423 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005424 case Match_UImm8_0:
5425 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5426 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005427 case Match_UImm10_0:
5428 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5429 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005430 case Match_SImm10_0:
5431 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5432 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005433 case Match_SImm11_0:
5434 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5435 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005436 case Match_UImm16:
5437 case Match_UImm16_Relaxed:
Petar Jovanovice4dacb72017-09-12 21:43:33 +00005438 case Match_UImm16_AltRelaxed:
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005439 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5440 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005441 case Match_SImm16:
5442 case Match_SImm16_Relaxed:
5443 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5444 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005445 case Match_SImm19_Lsl2:
5446 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5447 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005448 case Match_UImm20_0:
5449 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5450 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005451 case Match_UImm26_0:
5452 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5453 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005454 case Match_SImm32:
5455 case Match_SImm32_Relaxed:
5456 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5457 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005458 case Match_UImm32_Coerced:
5459 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5460 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005461 case Match_MemSImm9:
5462 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5463 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005464 case Match_MemSImm10:
5465 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5466 "expected memory with 10-bit signed offset");
5467 case Match_MemSImm10Lsl1:
5468 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5469 "expected memory with 11-bit signed offset and multiple of 2");
5470 case Match_MemSImm10Lsl2:
5471 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5472 "expected memory with 12-bit signed offset and multiple of 4");
5473 case Match_MemSImm10Lsl3:
5474 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5475 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005476 case Match_MemSImm11:
5477 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5478 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005479 case Match_MemSImm12:
5480 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5481 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005482 case Match_MemSImm16:
5483 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5484 "expected memory with 16-bit signed offset");
Simon Atanasyand4d892f2018-04-26 19:55:28 +00005485 case Match_MemSImmPtr:
5486 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5487 "expected memory with 32-bit signed offset");
Simon Dardis6f83ae32017-09-14 15:17:50 +00005488 case Match_RequiresPosSizeRange0_32: {
5489 SMLoc ErrorStart = Operands[3]->getStartLoc();
5490 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5491 return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
5492 SMRange(ErrorStart, ErrorEnd));
5493 }
Simon Dardis55e44672017-09-14 17:27:53 +00005494 case Match_RequiresPosSizeUImm6: {
5495 SMLoc ErrorStart = Operands[3]->getStartLoc();
5496 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5497 return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
5498 SMRange(ErrorStart, ErrorEnd));
5499 }
Simon Dardis6f83ae32017-09-14 15:17:50 +00005500 case Match_RequiresPosSizeRange33_64: {
5501 SMLoc ErrorStart = Operands[3]->getStartLoc();
5502 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5503 return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
5504 SMRange(ErrorStart, ErrorEnd));
5505 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005506 }
Craig Topper589ceee2015-01-03 08:16:34 +00005507
5508 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005509}
5510
Toma Tabacud9d344b2015-04-27 14:05:04 +00005511void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5512 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5513 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5514 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005515}
5516
Toma Tabacu81496c12015-05-20 08:54:45 +00005517void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5518 if (!AssemblerOptions.back()->isMacro())
5519 Warning(Loc, "macro instruction expanded into multiple instructions");
5520}
5521
Simon Dardis6a319922018-05-25 16:15:48 +00005522void MipsAsmParser::ConvertXWPOperands(MCInst &Inst,
5523 const OperandVector &Operands) {
5524 assert(
5525 (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) &&
5526 "Unexpected instruction!");
5527 ((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, 1);
5528 int NextReg = nextReg(((MipsOperand &)*Operands[1]).getGPR32Reg());
5529 Inst.addOperand(MCOperand::createReg(NextReg));
5530 ((MipsOperand &)*Operands[2]).addMemOperands(Inst, 2);
5531}
5532
Daniel Sandersef638fe2014-10-03 15:37:37 +00005533void
5534MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5535 SMRange Range, bool ShowColors) {
5536 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005537 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005538 ShowColors);
5539}
5540
Jack Carter1ac53222013-02-20 23:11:17 +00005541int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005542 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005543
Vladimir Medic4c299852013-11-06 11:27:05 +00005544 CC = StringSwitch<unsigned>(Name)
5545 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005546 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005547 .Case("a0", 4)
5548 .Case("a1", 5)
5549 .Case("a2", 6)
5550 .Case("a3", 7)
5551 .Case("v0", 2)
5552 .Case("v1", 3)
5553 .Case("s0", 16)
5554 .Case("s1", 17)
5555 .Case("s2", 18)
5556 .Case("s3", 19)
5557 .Case("s4", 20)
5558 .Case("s5", 21)
5559 .Case("s6", 22)
5560 .Case("s7", 23)
5561 .Case("k0", 26)
5562 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005563 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005564 .Case("sp", 29)
5565 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005566 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005567 .Case("ra", 31)
5568 .Case("t0", 8)
5569 .Case("t1", 9)
5570 .Case("t2", 10)
5571 .Case("t3", 11)
5572 .Case("t4", 12)
5573 .Case("t5", 13)
5574 .Case("t6", 14)
5575 .Case("t7", 15)
5576 .Case("t8", 24)
5577 .Case("t9", 25)
5578 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005579
Toma Tabacufda445c2014-09-15 15:33:01 +00005580 if (!(isABI_N32() || isABI_N64()))
5581 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005582
Daniel Sandersef638fe2014-10-03 15:37:37 +00005583 if (12 <= CC && CC <= 15) {
5584 // Name is one of t4-t7
5585 AsmToken RegTok = getLexer().peekTok();
5586 SMRange RegRange = RegTok.getLocRange();
5587
5588 StringRef FixedName = StringSwitch<StringRef>(Name)
5589 .Case("t4", "t0")
5590 .Case("t5", "t1")
5591 .Case("t6", "t2")
5592 .Case("t7", "t3")
5593 .Default("");
5594 assert(FixedName != "" && "Register name is not one of t4-t7.");
5595
5596 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5597 "Did you mean $" + FixedName + "?", RegRange);
5598 }
5599
Toma Tabacufda445c2014-09-15 15:33:01 +00005600 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5601 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5602 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5603 if (8 <= CC && CC <= 11)
5604 CC += 4;
5605
5606 if (CC == -1)
5607 CC = StringSwitch<unsigned>(Name)
5608 .Case("a4", 8)
5609 .Case("a5", 9)
5610 .Case("a6", 10)
5611 .Case("a7", 11)
5612 .Case("kt0", 26)
5613 .Case("kt1", 27)
5614 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005615
5616 return CC;
5617}
Jack Carterd0bd6422013-04-18 00:41:53 +00005618
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005619int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5620 int CC;
5621
5622 CC = StringSwitch<unsigned>(Name)
5623 .Case("hwr_cpunum", 0)
5624 .Case("hwr_synci_step", 1)
5625 .Case("hwr_cc", 2)
5626 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005627 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005628 .Default(-1);
5629
5630 return CC;
5631}
5632
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005633int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005634 if (Name[0] == 'f') {
5635 StringRef NumString = Name.substr(1);
5636 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005637 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005638 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005639 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005640 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005641 return IntVal;
5642 }
5643 return -1;
5644}
Jack Cartera63b16a2012-09-07 00:23:42 +00005645
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005646int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005647 if (Name.startswith("fcc")) {
5648 StringRef NumString = Name.substr(3);
5649 unsigned IntVal;
5650 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005651 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005652 if (IntVal > 7) // There are only 8 fcc registers.
5653 return -1;
5654 return IntVal;
5655 }
5656 return -1;
5657}
5658
5659int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005660 if (Name.startswith("ac")) {
5661 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005662 unsigned IntVal;
5663 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005664 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005665 if (IntVal > 3) // There are only 3 acc registers.
5666 return -1;
5667 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005668 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005669 return -1;
5670}
Jack Carterd0bd6422013-04-18 00:41:53 +00005671
Jack Carter5dc8ac92013-09-25 23:50:44 +00005672int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5673 unsigned IntVal;
5674
5675 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5676 return -1;
5677
5678 if (IntVal > 31)
5679 return -1;
5680
5681 return IntVal;
5682}
5683
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005684int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5685 int CC;
5686
5687 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005688 .Case("msair", 0)
5689 .Case("msacsr", 1)
5690 .Case("msaaccess", 2)
5691 .Case("msasave", 3)
5692 .Case("msamodify", 4)
5693 .Case("msarequest", 5)
5694 .Case("msamap", 6)
5695 .Case("msaunmap", 7)
5696 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005697
5698 return CC;
5699}
5700
Simon Dardis3aa8a902017-02-06 12:43:46 +00005701bool MipsAsmParser::canUseATReg() {
5702 return AssemblerOptions.back()->getATRegIndex() != 0;
5703}
5704
Toma Tabacu89a712b2015-04-15 10:48:56 +00005705unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005706 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005707 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005708 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005709 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005710 return 0;
5711 }
5712 unsigned AT = getReg(
5713 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005714 return AT;
5715}
Jack Carter0b744b32012-10-04 02:29:46 +00005716
Jack Carterd0bd6422013-04-18 00:41:53 +00005717unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005718 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005719}
5720
Toma Tabacu13964452014-09-04 13:23:44 +00005721bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005722 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005723 LLVM_DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005724
Jack Carter30a59822012-10-04 04:03:53 +00005725 // Check if the current operand has a custom associated parser, if so, try to
5726 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005727 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5728 if (ResTy == MatchOperand_Success)
5729 return false;
5730 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5731 // there was a match, but an error occurred, in which case, just return that
5732 // the operand parsing failed.
5733 if (ResTy == MatchOperand_ParseFail)
5734 return true;
5735
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005736 LLVM_DEBUG(dbgs() << ".. Generic Parser\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005737
Jack Carterb4dbc172012-09-05 23:34:03 +00005738 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005739 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005740 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005741 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005742
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005743 // Almost all registers have been parsed by custom parsers. There is only
5744 // one exception to this. $zero (and it's alias $0) will reach this point
5745 // for div, divu, and similar instructions because it is not an operand
5746 // to the instruction definition but an explicit register. Special case
5747 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005748 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005749 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005750
Jack Carterd0bd6422013-04-18 00:41:53 +00005751 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005752 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005753 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005754 return true;
5755
Jack Carter873c7242013-01-12 01:03:14 +00005756 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005757 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005758 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005759 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005760 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005761
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005762 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005763 return false;
5764 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005765 default: {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005766 LLVM_DEBUG(dbgs() << ".. generic integer expression\n");
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005767
5768 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005769 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005770 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005771 return true;
5772
Jack Carter873c7242013-01-12 01:03:14 +00005773 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5774
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005775 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005776 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005777 }
Jack Carter0b744b32012-10-04 02:29:46 +00005778 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005779 return true;
5780}
5781
Jack Carterb5cf5902013-04-17 00:18:04 +00005782bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005783 switch (Expr->getKind()) {
5784 case MCExpr::Constant:
5785 return true;
5786 case MCExpr::SymbolRef:
5787 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
Simon Dardisc6be2252017-08-09 10:47:52 +00005788 case MCExpr::Binary: {
Simon Dardis02c9a3d2017-08-18 13:27:02 +00005789 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
Simon Dardisc6be2252017-08-09 10:47:52 +00005790 if (!isEvaluated(BE->getLHS()))
5791 return false;
5792 return isEvaluated(BE->getRHS());
5793 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005794 case MCExpr::Unary:
5795 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005796 case MCExpr::Target:
5797 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005798 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005799 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005800}
Jack Carterd0bd6422013-04-18 00:41:53 +00005801
Jack Carterb4dbc172012-09-05 23:34:03 +00005802bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5803 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005804 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005805 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005806 if (ResTy == MatchOperand_Success) {
5807 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005808 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005809 StartLoc = Operand.getStartLoc();
5810 EndLoc = Operand.getEndLoc();
5811
5812 // AFAIK, we only support numeric registers and named GPR's in CFI
5813 // directives.
5814 // Don't worry about eating tokens before failing. Using an unrecognised
5815 // register is a parse error.
5816 if (Operand.isGPRAsmReg()) {
5817 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005818 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005819 }
5820
5821 return (RegNo == (unsigned)-1);
5822 }
5823
5824 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005825 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005826}
5827
Jack Carterb5cf5902013-04-17 00:18:04 +00005828bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005829 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005830
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005831 if (isParenExpr)
5832 return getParser().parseParenExprOfDepth(0, Res, S);
5833 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005834}
5835
Alex Bradbury58eba092016-11-01 16:32:05 +00005836OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005837MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005838 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005839 LLVM_DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005840 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005841 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005842 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005843 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005844 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005845 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005846
Jack Carterb5cf5902013-04-17 00:18:04 +00005847 if (getLexer().getKind() == AsmToken::LParen) {
5848 Parser.Lex();
5849 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005850 }
5851
Jack Carterb5cf5902013-04-17 00:18:04 +00005852 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005853 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005854 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005855
Jack Carterd0bd6422013-04-18 00:41:53 +00005856 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005857 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005858 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005859 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005860 SMLoc E =
5861 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005862 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005863 return MatchOperand_Success;
5864 }
5865 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005866 SMLoc E =
5867 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005868
Jack Carterd0bd6422013-04-18 00:41:53 +00005869 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005870 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005871 auto Base = MipsOperand::createGPRReg(
5872 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005873 Operands.push_back(
5874 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005875 return MatchOperand_Success;
5876 }
Simon Dardis858915f2016-10-18 15:17:17 +00005877 MCBinaryExpr::Opcode Opcode;
5878 // GAS and LLVM treat comparison operators different. GAS will generate -1
5879 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5880 // highly unlikely to be found in a memory offset expression, we don't
5881 // handle them.
5882 switch (Tok.getKind()) {
5883 case AsmToken::Plus:
5884 Opcode = MCBinaryExpr::Add;
5885 Parser.Lex();
5886 break;
5887 case AsmToken::Minus:
5888 Opcode = MCBinaryExpr::Sub;
5889 Parser.Lex();
5890 break;
5891 case AsmToken::Star:
5892 Opcode = MCBinaryExpr::Mul;
5893 Parser.Lex();
5894 break;
5895 case AsmToken::Pipe:
5896 Opcode = MCBinaryExpr::Or;
5897 Parser.Lex();
5898 break;
5899 case AsmToken::Amp:
5900 Opcode = MCBinaryExpr::And;
5901 Parser.Lex();
5902 break;
5903 case AsmToken::LessLess:
5904 Opcode = MCBinaryExpr::Shl;
5905 Parser.Lex();
5906 break;
5907 case AsmToken::GreaterGreater:
5908 Opcode = MCBinaryExpr::LShr;
5909 Parser.Lex();
5910 break;
5911 case AsmToken::Caret:
5912 Opcode = MCBinaryExpr::Xor;
5913 Parser.Lex();
5914 break;
5915 case AsmToken::Slash:
5916 Opcode = MCBinaryExpr::Div;
5917 Parser.Lex();
5918 break;
5919 case AsmToken::Percent:
5920 Opcode = MCBinaryExpr::Mod;
5921 Parser.Lex();
5922 break;
5923 default:
5924 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5925 return MatchOperand_ParseFail;
5926 }
5927 const MCExpr * NextExpr;
5928 if (getParser().parseExpression(NextExpr))
5929 return MatchOperand_ParseFail;
5930 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005931 }
5932
Jack Carterd0bd6422013-04-18 00:41:53 +00005933 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005934 }
5935
Toma Tabacu13964452014-09-04 13:23:44 +00005936 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005937 if (Res != MatchOperand_Success)
5938 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005939
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005940 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005941 Error(Parser.getTok().getLoc(), "')' expected");
5942 return MatchOperand_ParseFail;
5943 }
5944
Jack Carter873c7242013-01-12 01:03:14 +00005945 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5946
Jack Carterd0bd6422013-04-18 00:41:53 +00005947 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005948
Craig Topper062a2ba2014-04-25 05:30:21 +00005949 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005950 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005951
Jack Carterd0bd6422013-04-18 00:41:53 +00005952 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005953 std::unique_ptr<MipsOperand> op(
5954 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005955 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005956 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005957 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005958 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005959 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5960 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005961 if (IdVal->evaluateAsAbsolute(Imm))
5962 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005963 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005964 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005965 getContext());
5966 }
5967
David Blaikie960ea3f2014-06-08 16:18:35 +00005968 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005969 return MatchOperand_Success;
5970}
5971
David Blaikie960ea3f2014-06-08 16:18:35 +00005972bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005973 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005974 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00005975 if (!Sym)
5976 return false;
5977
5978 SMLoc S = Parser.getTok().getLoc();
5979 if (Sym->isVariable()) {
5980 const MCExpr *Expr = Sym->getVariableValue();
Jack Carterd76b2372013-03-21 21:44:16 +00005981 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005982 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005983 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005984 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005985 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005986 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005987 if (ResTy == MatchOperand_Success) {
5988 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005989 return true;
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00005990 }
5991 if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005992 llvm_unreachable("Should never ParseFail");
Jack Carterd76b2372013-03-21 21:44:16 +00005993 }
Jack Carterd76b2372013-03-21 21:44:16 +00005994 }
Simon Atanasyan69301c92018-05-29 15:58:06 +00005995 } else if (Sym->isUnset()) {
5996 // If symbol is unset, it might be created in the `parseSetAssignment`
5997 // routine as an alias for a numeric register name.
5998 // Lookup in the aliases list.
5999 auto Entry = RegisterSets.find(Sym->getName());
6000 if (Entry != RegisterSets.end()) {
6001 OperandMatchResultTy ResTy =
6002 matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S);
6003 if (ResTy == MatchOperand_Success) {
6004 Parser.Lex();
6005 return true;
6006 }
6007 }
Jack Carterd76b2372013-03-21 21:44:16 +00006008 }
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00006009
Jack Carterd76b2372013-03-21 21:44:16 +00006010 return false;
6011}
Jack Carterd0bd6422013-04-18 00:41:53 +00006012
Alex Bradbury58eba092016-11-01 16:32:05 +00006013OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006014MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00006015 StringRef Identifier,
6016 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006017 int Index = matchCPURegisterName(Identifier);
6018 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006019 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006020 Index, Identifier, getContext().getRegisterInfo(), S,
6021 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006022 return MatchOperand_Success;
6023 }
6024
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00006025 Index = matchHWRegsRegisterName(Identifier);
6026 if (Index != -1) {
6027 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006028 Index, Identifier, getContext().getRegisterInfo(), S,
6029 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00006030 return MatchOperand_Success;
6031 }
6032
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006033 Index = matchFPURegisterName(Identifier);
6034 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006035 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006036 Index, Identifier, getContext().getRegisterInfo(), S,
6037 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006038 return MatchOperand_Success;
6039 }
6040
6041 Index = matchFCCRegisterName(Identifier);
6042 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006043 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006044 Index, Identifier, getContext().getRegisterInfo(), S,
6045 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006046 return MatchOperand_Success;
6047 }
6048
6049 Index = matchACRegisterName(Identifier);
6050 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006051 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006052 Index, Identifier, getContext().getRegisterInfo(), S,
6053 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006054 return MatchOperand_Success;
6055 }
6056
6057 Index = matchMSA128RegisterName(Identifier);
6058 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006059 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006060 Index, Identifier, getContext().getRegisterInfo(), S,
6061 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006062 return MatchOperand_Success;
6063 }
6064
6065 Index = matchMSA128CtrlRegisterName(Identifier);
6066 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006067 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006068 Index, Identifier, getContext().getRegisterInfo(), S,
6069 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006070 return MatchOperand_Success;
6071 }
6072
6073 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00006074}
6075
Alex Bradbury58eba092016-11-01 16:32:05 +00006076OperandMatchResultTy
Simon Atanasyan69301c92018-05-29 15:58:06 +00006077MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands,
6078 const AsmToken &Token, SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006079 if (Token.is(AsmToken::Identifier)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006080 LLVM_DEBUG(dbgs() << ".. identifier\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006081 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00006082 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00006083 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00006084 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006085 } else if (Token.is(AsmToken::Integer)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006086 LLVM_DEBUG(dbgs() << ".. integer\n");
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006087 int64_t RegNum = Token.getIntVal();
6088 if (RegNum < 0 || RegNum > 31) {
6089 // Show the error, but treat invalid register
6090 // number as a normal one to continue parsing
6091 // and catch other possible errors.
6092 Error(getLexer().getLoc(), "invalid register number");
6093 }
Toma Tabacu13964452014-09-04 13:23:44 +00006094 Operands.push_back(MipsOperand::createNumericReg(
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006095 RegNum, Token.getString(), getContext().getRegisterInfo(), S,
Daniel Sandersc5537422016-07-27 13:49:44 +00006096 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006097 return MatchOperand_Success;
6098 }
6099
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00006100 LLVM_DEBUG(dbgs() << Token.getKind() << "\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006101
6102 return MatchOperand_NoMatch;
6103}
6104
Alex Bradbury58eba092016-11-01 16:32:05 +00006105OperandMatchResultTy
Simon Atanasyan69301c92018-05-29 15:58:06 +00006106MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
6107 auto Token = getLexer().peekTok(false);
6108 return matchAnyRegisterWithoutDollar(Operands, Token, S);
6109}
6110
6111OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006112MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006113 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006114 LLVM_DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006115
6116 auto Token = Parser.getTok();
6117
6118 SMLoc S = Token.getLoc();
6119
6120 if (Token.isNot(AsmToken::Dollar)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006121 LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006122 if (Token.is(AsmToken::Identifier)) {
6123 if (searchSymbolAlias(Operands))
6124 return MatchOperand_Success;
6125 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006126 LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006127 return MatchOperand_NoMatch;
6128 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006129 LLVM_DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006130
Toma Tabacu13964452014-09-04 13:23:44 +00006131 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00006132 if (ResTy == MatchOperand_Success) {
6133 Parser.Lex(); // $
6134 Parser.Lex(); // identifier
6135 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006136 return ResTy;
6137}
6138
Alex Bradbury58eba092016-11-01 16:32:05 +00006139OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006140MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006141 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006142 LLVM_DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006143
6144 SMLoc S = getLexer().getLoc();
6145
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006146 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006147 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006148 if (ResTy != MatchOperand_NoMatch)
6149 return ResTy;
6150
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006151 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00006152 const MCExpr *Expr = nullptr;
6153 if (Parser.parseExpression(Expr)) {
6154 // We have no way of knowing if a symbol was consumed so we must ParseFail
6155 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006156 }
Daniel Sandersffd84362014-04-01 10:41:48 +00006157 Operands.push_back(
6158 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006159 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00006160}
6161
Alex Bradbury58eba092016-11-01 16:32:05 +00006162OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00006163MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006164 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00006165 const MCExpr *IdVal;
Simon Dardisa17a7b62017-10-10 13:34:45 +00006166 // If the first token is '$' we may have register operand. We have to reject
6167 // cases where it is not a register. Complicating the matter is that
6168 // register names are not reserved across all ABIs.
6169 // Peek past the dollar to see if it's a register name for this ABI.
Vladimir Medic2b953d02013-10-01 09:48:56 +00006170 SMLoc S = Parser.getTok().getLoc();
Simon Dardisa17a7b62017-10-10 13:34:45 +00006171 if (Parser.getTok().is(AsmToken::Dollar)) {
6172 return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
6173 ? MatchOperand_ParseFail
6174 : MatchOperand_NoMatch;
6175 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00006176 if (getParser().parseExpression(IdVal))
6177 return MatchOperand_ParseFail;
6178 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Simon Dardisa17a7b62017-10-10 13:34:45 +00006179 if (!MCE)
6180 return MatchOperand_NoMatch;
Vladimir Medic2b953d02013-10-01 09:48:56 +00006181 int64_t Val = MCE->getValue();
6182 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
6183 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00006184 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00006185 return MatchOperand_Success;
6186}
6187
Alex Bradbury58eba092016-11-01 16:32:05 +00006188OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006189MipsAsmParser::parseRegisterList(OperandVector &Operands) {
6190 MCAsmParser &Parser = getParser();
6191 SmallVector<unsigned, 10> Regs;
6192 unsigned RegNo;
6193 unsigned PrevReg = Mips::NoRegister;
6194 bool RegRange = false;
6195 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6196
6197 if (Parser.getTok().isNot(AsmToken::Dollar))
6198 return MatchOperand_ParseFail;
6199
6200 SMLoc S = Parser.getTok().getLoc();
6201 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
6202 SMLoc E = getLexer().getLoc();
6203 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
6204 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
6205 if (RegRange) {
6206 // Remove last register operand because registers from register range
6207 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006208 if ((isGP64bit() && RegNo == Mips::RA_64) ||
6209 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006210 Regs.push_back(RegNo);
6211 } else {
6212 unsigned TmpReg = PrevReg + 1;
6213 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006214 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
6215 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
6216 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006217 Error(E, "invalid register operand");
6218 return MatchOperand_ParseFail;
6219 }
6220
6221 PrevReg = TmpReg;
6222 Regs.push_back(TmpReg++);
6223 }
6224 }
6225
6226 RegRange = false;
6227 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006228 if ((PrevReg == Mips::NoRegister) &&
6229 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
6230 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006231 Error(E, "$16 or $31 expected");
6232 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006233 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
6234 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
6235 !isGP64bit()) ||
6236 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
6237 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
6238 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006239 Error(E, "invalid register operand");
6240 return MatchOperand_ParseFail;
6241 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006242 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
6243 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
6244 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006245 Error(E, "consecutive register numbers expected");
6246 return MatchOperand_ParseFail;
6247 }
6248
6249 Regs.push_back(RegNo);
6250 }
6251
6252 if (Parser.getTok().is(AsmToken::Minus))
6253 RegRange = true;
6254
6255 if (!Parser.getTok().isNot(AsmToken::Minus) &&
6256 !Parser.getTok().isNot(AsmToken::Comma)) {
6257 Error(E, "',' or '-' expected");
6258 return MatchOperand_ParseFail;
6259 }
6260
6261 Lex(); // Consume comma or minus
6262 if (Parser.getTok().isNot(AsmToken::Dollar))
6263 break;
6264
6265 PrevReg = RegNo;
6266 }
6267
6268 SMLoc E = Parser.getTok().getLoc();
6269 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6270 parseMemOperand(Operands);
6271 return MatchOperand_Success;
6272}
6273
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006274/// Sometimes (i.e. load/stores) the operand may be followed immediately by
6275/// either this.
6276/// ::= '(', register, ')'
6277/// handle it before we iterate so we don't get tripped up by the lack of
6278/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006279bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006280 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006281 if (getLexer().is(AsmToken::LParen)) {
6282 Operands.push_back(
6283 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
6284 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006285 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006286 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006287 return Error(Loc, "unexpected token in argument list");
6288 }
6289 if (Parser.getTok().isNot(AsmToken::RParen)) {
6290 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006291 return Error(Loc, "unexpected token, expected ')'");
6292 }
6293 Operands.push_back(
6294 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
6295 Parser.Lex();
6296 }
6297 return false;
6298}
6299
6300/// Sometimes (i.e. in MSA) the operand may be followed immediately by
6301/// either one of these.
6302/// ::= '[', register, ']'
6303/// ::= '[', integer, ']'
6304/// handle it before we iterate so we don't get tripped up by the lack of
6305/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006306bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00006307 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006308 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006309 if (getLexer().is(AsmToken::LBrac)) {
6310 Operands.push_back(
6311 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
6312 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006313 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006314 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006315 return Error(Loc, "unexpected token in argument list");
6316 }
6317 if (Parser.getTok().isNot(AsmToken::RBrac)) {
6318 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006319 return Error(Loc, "unexpected token, expected ']'");
6320 }
6321 Operands.push_back(
6322 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
6323 Parser.Lex();
6324 }
6325 return false;
6326}
6327
Simon Atanasyanc49da2e2018-09-13 08:38:03 +00006328static std::string MipsMnemonicSpellCheck(StringRef S, uint64_t FBS,
6329 unsigned VariantID = 0);
6330
David Blaikie960ea3f2014-06-08 16:18:35 +00006331bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6332 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006333 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006334 LLVM_DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006335
6336 // We have reached first instruction, module directive are now forbidden.
6337 getTargetStreamer().forbidModuleDirective();
6338
Vladimir Medic74593e62013-07-17 15:00:42 +00006339 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006340 if (!mnemonicIsValid(Name, 0)) {
Simon Atanasyanc49da2e2018-09-13 08:38:03 +00006341 uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
6342 std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS);
6343 return Error(NameLoc, "unknown instruction" + Suggestion);
Vladimir Medic74593e62013-07-17 15:00:42 +00006344 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006345 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006346 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006347
6348 // Read the remaining operands.
6349 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6350 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006351 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006352 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006353 return Error(Loc, "unexpected token in argument list");
6354 }
Toma Tabacu13964452014-09-04 13:23:44 +00006355 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006356 return true;
6357 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006358
Jack Carterd0bd6422013-04-18 00:41:53 +00006359 while (getLexer().is(AsmToken::Comma)) {
6360 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006361 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006362 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006363 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006364 return Error(Loc, "unexpected token in argument list");
6365 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006366 // Parse bracket and parenthesis suffixes before we iterate
6367 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006368 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006369 return true;
6370 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006371 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006372 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006373 }
6374 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006375 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6376 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006377 return Error(Loc, "unexpected token in argument list");
6378 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006379 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006380 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006381}
6382
Nirav Dave996fc132016-05-05 14:15:46 +00006383// FIXME: Given that these have the same name, these should both be
6384// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006385bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006386 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006387 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006388}
6389
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006390bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006391 return Error(Loc, ErrorMsg);
6392}
6393
Jack Carter0b744b32012-10-04 02:29:46 +00006394bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006395 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006396 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006397
6398 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006399 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006400
6401 Parser.Lex(); // Eat "noat".
6402
Jack Carterd0bd6422013-04-18 00:41:53 +00006403 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006404 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006405 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006406 return false;
6407 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006408
6409 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006410 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006411 return false;
6412}
Jack Carterd0bd6422013-04-18 00:41:53 +00006413
Jack Carter0b744b32012-10-04 02:29:46 +00006414bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006415 // Line can be: ".set at", which sets $at to $1
6416 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006417 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006418 Parser.Lex(); // Eat "at".
6419
Jack Carter0b744b32012-10-04 02:29:46 +00006420 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006421 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006422 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006423
6424 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006425 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006426 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006427 }
6428
6429 if (getLexer().isNot(AsmToken::Equal)) {
6430 reportParseError("unexpected token, expected equals sign");
6431 return false;
6432 }
6433 Parser.Lex(); // Eat "=".
6434
6435 if (getLexer().isNot(AsmToken::Dollar)) {
6436 if (getLexer().is(AsmToken::EndOfStatement)) {
6437 reportParseError("no register specified");
6438 return false;
6439 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006440 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006441 return false;
6442 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006443 }
6444 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006445
Toma Tabacu16a74492015-02-13 10:30:57 +00006446 // Find out what "reg" is.
6447 unsigned AtRegNo;
6448 const AsmToken &Reg = Parser.getTok();
6449 if (Reg.is(AsmToken::Identifier)) {
6450 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6451 } else if (Reg.is(AsmToken::Integer)) {
6452 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006453 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006454 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006455 return false;
6456 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006457
6458 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006459 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006460 reportParseError("invalid register");
6461 return false;
6462 }
6463 Parser.Lex(); // Eat "reg".
6464
6465 // If this is not the end of the statement, report an error.
6466 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6467 reportParseError("unexpected token, expected end of statement");
6468 return false;
6469 }
6470
6471 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6472
6473 Parser.Lex(); // Consume the EndOfStatement.
6474 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006475}
6476
6477bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006478 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006479 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006480 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006481 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006482 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006483 return false;
6484 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006485 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006486 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006487 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006488 return false;
6489}
6490
6491bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006492 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006493 Parser.Lex();
6494 // If this is not the end of the statement, report an error.
6495 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006496 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006497 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006498 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006499 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006500 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006501 Parser.Lex(); // Consume the EndOfStatement.
6502 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006503}
6504
6505bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006506 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006507 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006508 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006509 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006510 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006511 return false;
6512 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006513 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006514 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006515 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006516 return false;
6517}
6518
6519bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006520 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006521 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006522 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006523 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006524 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006525 return false;
6526 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006527 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006528 reportParseError("`noreorder' must be set before `nomacro'");
6529 return false;
6530 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006531 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006532 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006533 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006534 return false;
6535}
Jack Carterd76b2372013-03-21 21:44:16 +00006536
Daniel Sanders44934432014-08-07 12:03:36 +00006537bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006538 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006539 Parser.Lex();
6540
6541 // If this is not the end of the statement, report an error.
6542 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006543 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006544
6545 setFeatureBits(Mips::FeatureMSA, "msa");
6546 getTargetStreamer().emitDirectiveSetMsa();
6547 return false;
6548}
6549
6550bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006551 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006552 Parser.Lex();
6553
6554 // If this is not the end of the statement, report an error.
6555 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006556 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006557
6558 clearFeatureBits(Mips::FeatureMSA, "msa");
6559 getTargetStreamer().emitDirectiveSetNoMsa();
6560 return false;
6561}
6562
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006563bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006564 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006565 Parser.Lex(); // Eat "nodsp".
6566
6567 // If this is not the end of the statement, report an error.
6568 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6569 reportParseError("unexpected token, expected end of statement");
6570 return false;
6571 }
6572
6573 clearFeatureBits(Mips::FeatureDSP, "dsp");
6574 getTargetStreamer().emitDirectiveSetNoDsp();
6575 return false;
6576}
6577
Toma Tabacucc2502d2014-11-04 17:18:07 +00006578bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006579 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006580 Parser.Lex(); // Eat "mips16".
6581
Jack Carter39536722014-01-22 23:08:42 +00006582 // If this is not the end of the statement, report an error.
6583 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006584 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006585 return false;
6586 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006587
6588 setFeatureBits(Mips::FeatureMips16, "mips16");
6589 getTargetStreamer().emitDirectiveSetMips16();
6590 Parser.Lex(); // Consume the EndOfStatement.
6591 return false;
6592}
6593
6594bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006595 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006596 Parser.Lex(); // Eat "nomips16".
6597
6598 // If this is not the end of the statement, report an error.
6599 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6600 reportParseError("unexpected token, expected end of statement");
6601 return false;
6602 }
6603
6604 clearFeatureBits(Mips::FeatureMips16, "mips16");
6605 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006606 Parser.Lex(); // Consume the EndOfStatement.
6607 return false;
6608}
6609
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006610bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006611 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006612 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006613 // Line can be: .set fp=32
6614 // .set fp=xx
6615 // .set fp=64
6616 Parser.Lex(); // Eat fp token
6617 AsmToken Tok = Parser.getTok();
6618 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006619 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006620 return false;
6621 }
6622 Parser.Lex(); // Eat '=' token.
6623 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006624
6625 if (!parseFpABIValue(FpAbiVal, ".set"))
6626 return false;
6627
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006628 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006629 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006630 return false;
6631 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006632 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006633 Parser.Lex(); // Consume the EndOfStatement.
6634 return false;
6635}
6636
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006637bool MipsAsmParser::parseSetOddSPRegDirective() {
6638 MCAsmParser &Parser = getParser();
6639
6640 Parser.Lex(); // Eat "oddspreg".
6641 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6642 reportParseError("unexpected token, expected end of statement");
6643 return false;
6644 }
6645
6646 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6647 getTargetStreamer().emitDirectiveSetOddSPReg();
6648 return false;
6649}
6650
6651bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6652 MCAsmParser &Parser = getParser();
6653
6654 Parser.Lex(); // Eat "nooddspreg".
6655 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6656 reportParseError("unexpected token, expected end of statement");
6657 return false;
6658 }
6659
6660 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6661 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6662 return false;
6663}
6664
Simon Dardis805f1e02017-07-11 21:28:36 +00006665bool MipsAsmParser::parseSetMtDirective() {
6666 MCAsmParser &Parser = getParser();
6667 Parser.Lex(); // Eat "mt".
6668
6669 // If this is not the end of the statement, report an error.
6670 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6671 reportParseError("unexpected token, expected end of statement");
6672 return false;
6673 }
6674
6675 setFeatureBits(Mips::FeatureMT, "mt");
6676 getTargetStreamer().emitDirectiveSetMt();
6677 Parser.Lex(); // Consume the EndOfStatement.
6678 return false;
6679}
6680
6681bool MipsAsmParser::parseSetNoMtDirective() {
6682 MCAsmParser &Parser = getParser();
6683 Parser.Lex(); // Eat "nomt".
6684
6685 // If this is not the end of the statement, report an error.
6686 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6687 reportParseError("unexpected token, expected end of statement");
6688 return false;
6689 }
6690
6691 clearFeatureBits(Mips::FeatureMT, "mt");
6692
6693 getTargetStreamer().emitDirectiveSetNoMt();
6694 Parser.Lex(); // Consume the EndOfStatement.
6695 return false;
6696}
6697
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006698bool MipsAsmParser::parseSetNoCRCDirective() {
6699 MCAsmParser &Parser = getParser();
6700 Parser.Lex(); // Eat "nocrc".
6701
6702 // If this is not the end of the statement, report an error.
6703 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6704 reportParseError("unexpected token, expected end of statement");
6705 return false;
6706 }
6707
6708 clearFeatureBits(Mips::FeatureCRC, "crc");
6709
6710 getTargetStreamer().emitDirectiveSetNoCRC();
6711 Parser.Lex(); // Consume the EndOfStatement.
6712 return false;
6713}
6714
Petar Jovanovicd4349f32018-04-27 09:12:08 +00006715bool MipsAsmParser::parseSetNoVirtDirective() {
6716 MCAsmParser &Parser = getParser();
6717 Parser.Lex(); // Eat "novirt".
6718
6719 // If this is not the end of the statement, report an error.
6720 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6721 reportParseError("unexpected token, expected end of statement");
6722 return false;
6723 }
6724
6725 clearFeatureBits(Mips::FeatureVirt, "virt");
6726
6727 getTargetStreamer().emitDirectiveSetNoVirt();
6728 Parser.Lex(); // Consume the EndOfStatement.
6729 return false;
6730}
6731
Petar Jovanovicdaf51692018-05-17 16:30:32 +00006732bool MipsAsmParser::parseSetNoGINVDirective() {
6733 MCAsmParser &Parser = getParser();
6734 Parser.Lex(); // Eat "noginv".
6735
6736 // If this is not the end of the statement, report an error.
6737 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6738 reportParseError("unexpected token, expected end of statement");
6739 return false;
6740 }
6741
6742 clearFeatureBits(Mips::FeatureGINV, "ginv");
6743
6744 getTargetStreamer().emitDirectiveSetNoGINV();
6745 Parser.Lex(); // Consume the EndOfStatement.
6746 return false;
6747}
6748
Toma Tabacu9db22db2014-09-09 10:15:38 +00006749bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006750 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006751 SMLoc Loc = getLexer().getLoc();
6752
6753 Parser.Lex();
6754 if (getLexer().isNot(AsmToken::EndOfStatement))
6755 return reportParseError("unexpected token, expected end of statement");
6756
6757 // Always keep an element on the options "stack" to prevent the user
6758 // from changing the initial options. This is how we remember them.
6759 if (AssemblerOptions.size() == 2)
6760 return reportParseError(Loc, ".set pop with no .set push");
6761
Akira Hatanakab11ef082015-11-14 06:35:56 +00006762 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006763 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006764 setAvailableFeatures(
6765 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6766 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006767
6768 getTargetStreamer().emitDirectiveSetPop();
6769 return false;
6770}
6771
6772bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006773 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006774 Parser.Lex();
6775 if (getLexer().isNot(AsmToken::EndOfStatement))
6776 return reportParseError("unexpected token, expected end of statement");
6777
6778 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006779 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006780 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006781
6782 getTargetStreamer().emitDirectiveSetPush();
6783 return false;
6784}
6785
Toma Tabacu29696502015-06-02 09:48:04 +00006786bool MipsAsmParser::parseSetSoftFloatDirective() {
6787 MCAsmParser &Parser = getParser();
6788 Parser.Lex();
6789 if (getLexer().isNot(AsmToken::EndOfStatement))
6790 return reportParseError("unexpected token, expected end of statement");
6791
6792 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6793 getTargetStreamer().emitDirectiveSetSoftFloat();
6794 return false;
6795}
6796
6797bool MipsAsmParser::parseSetHardFloatDirective() {
6798 MCAsmParser &Parser = getParser();
6799 Parser.Lex();
6800 if (getLexer().isNot(AsmToken::EndOfStatement))
6801 return reportParseError("unexpected token, expected end of statement");
6802
6803 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6804 getTargetStreamer().emitDirectiveSetHardFloat();
6805 return false;
6806}
6807
Jack Carterd76b2372013-03-21 21:44:16 +00006808bool MipsAsmParser::parseSetAssignment() {
6809 StringRef Name;
6810 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006811 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006812
6813 if (Parser.parseIdentifier(Name))
Simon Atanasyan3535cb12018-05-29 09:51:22 +00006814 return reportParseError("expected identifier after .set");
Jack Carterd76b2372013-03-21 21:44:16 +00006815
6816 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006817 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006818 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006819
Simon Atanasyan69301c92018-05-29 15:58:06 +00006820 if (getLexer().is(AsmToken::Dollar) &&
6821 getLexer().peekTok().is(AsmToken::Integer)) {
6822 // Parse assignment of a numeric register:
6823 // .set r1,$1
6824 Parser.Lex(); // Eat $.
6825 RegisterSets[Name] = Parser.getTok();
6826 Parser.Lex(); // Eat identifier.
6827 getContext().getOrCreateSymbol(Name);
6828 } else if (!Parser.parseExpression(Value)) {
6829 // Parse assignment of an expression including
6830 // symbolic registers:
6831 // .set $tmp, $BB0-$BB1
6832 // .set r2, $f2
6833 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
6834 Sym->setVariableValue(Value);
6835 } else {
Jack Carter02593002013-05-28 22:21:05 +00006836 return reportParseError("expected valid expression after comma");
Simon Atanasyan69301c92018-05-29 15:58:06 +00006837 }
Jack Carterd76b2372013-03-21 21:44:16 +00006838
6839 return false;
6840}
Jack Carterd0bd6422013-04-18 00:41:53 +00006841
Toma Tabacu26647792014-09-09 12:52:14 +00006842bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006843 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006844 Parser.Lex();
6845 if (getLexer().isNot(AsmToken::EndOfStatement))
6846 return reportParseError("unexpected token, expected end of statement");
6847
6848 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006849 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006850 setAvailableFeatures(
6851 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6852 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006853 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6854
6855 getTargetStreamer().emitDirectiveSetMips0();
6856 return false;
6857}
6858
Toma Tabacu85618b32014-08-19 14:22:52 +00006859bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006860 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006861 Parser.Lex();
6862 if (getLexer().isNot(AsmToken::Equal))
6863 return reportParseError("unexpected token, expected equals sign");
6864
6865 Parser.Lex();
6866 StringRef Arch;
6867 if (Parser.parseIdentifier(Arch))
6868 return reportParseError("expected arch identifier");
6869
6870 StringRef ArchFeatureName =
6871 StringSwitch<StringRef>(Arch)
6872 .Case("mips1", "mips1")
6873 .Case("mips2", "mips2")
6874 .Case("mips3", "mips3")
6875 .Case("mips4", "mips4")
6876 .Case("mips5", "mips5")
6877 .Case("mips32", "mips32")
6878 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006879 .Case("mips32r3", "mips32r3")
6880 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006881 .Case("mips32r6", "mips32r6")
6882 .Case("mips64", "mips64")
6883 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006884 .Case("mips64r3", "mips64r3")
6885 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006886 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006887 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006888 .Case("r4000", "mips3") // This is an implementation of Mips3.
6889 .Default("");
6890
6891 if (ArchFeatureName.empty())
6892 return reportParseError("unsupported architecture");
6893
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00006894 if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
6895 return reportParseError("mips64r6 does not support microMIPS");
6896
Toma Tabacu85618b32014-08-19 14:22:52 +00006897 selectArch(ArchFeatureName);
6898 getTargetStreamer().emitDirectiveSetArch(Arch);
6899 return false;
6900}
6901
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006902bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006903 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006904 Parser.Lex();
6905 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006906 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006907
Matheus Almeida2852af82014-04-22 10:15:54 +00006908 switch (Feature) {
6909 default:
6910 llvm_unreachable("Unimplemented feature");
6911 case Mips::FeatureDSP:
6912 setFeatureBits(Mips::FeatureDSP, "dsp");
6913 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006914 break;
Petar Jovanovic65f10242017-10-05 17:40:32 +00006915 case Mips::FeatureDSPR2:
6916 setFeatureBits(Mips::FeatureDSPR2, "dspr2");
6917 getTargetStreamer().emitDirectiveSetDspr2();
6918 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006919 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006920 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006921 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006922 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006923 case Mips::FeatureMips1:
6924 selectArch("mips1");
6925 getTargetStreamer().emitDirectiveSetMips1();
6926 break;
6927 case Mips::FeatureMips2:
6928 selectArch("mips2");
6929 getTargetStreamer().emitDirectiveSetMips2();
6930 break;
6931 case Mips::FeatureMips3:
6932 selectArch("mips3");
6933 getTargetStreamer().emitDirectiveSetMips3();
6934 break;
6935 case Mips::FeatureMips4:
6936 selectArch("mips4");
6937 getTargetStreamer().emitDirectiveSetMips4();
6938 break;
6939 case Mips::FeatureMips5:
6940 selectArch("mips5");
6941 getTargetStreamer().emitDirectiveSetMips5();
6942 break;
6943 case Mips::FeatureMips32:
6944 selectArch("mips32");
6945 getTargetStreamer().emitDirectiveSetMips32();
6946 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006947 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006948 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006949 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006950 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006951 case Mips::FeatureMips32r3:
6952 selectArch("mips32r3");
6953 getTargetStreamer().emitDirectiveSetMips32R3();
6954 break;
6955 case Mips::FeatureMips32r5:
6956 selectArch("mips32r5");
6957 getTargetStreamer().emitDirectiveSetMips32R5();
6958 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006959 case Mips::FeatureMips32r6:
6960 selectArch("mips32r6");
6961 getTargetStreamer().emitDirectiveSetMips32R6();
6962 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006963 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006964 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006965 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006966 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006967 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006968 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006969 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006970 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006971 case Mips::FeatureMips64r3:
6972 selectArch("mips64r3");
6973 getTargetStreamer().emitDirectiveSetMips64R3();
6974 break;
6975 case Mips::FeatureMips64r5:
6976 selectArch("mips64r5");
6977 getTargetStreamer().emitDirectiveSetMips64R5();
6978 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006979 case Mips::FeatureMips64r6:
6980 selectArch("mips64r6");
6981 getTargetStreamer().emitDirectiveSetMips64R6();
6982 break;
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006983 case Mips::FeatureCRC:
6984 setFeatureBits(Mips::FeatureCRC, "crc");
6985 getTargetStreamer().emitDirectiveSetCRC();
6986 break;
Petar Jovanovicd4349f32018-04-27 09:12:08 +00006987 case Mips::FeatureVirt:
6988 setFeatureBits(Mips::FeatureVirt, "virt");
6989 getTargetStreamer().emitDirectiveSetVirt();
6990 break;
Petar Jovanovicdaf51692018-05-17 16:30:32 +00006991 case Mips::FeatureGINV:
6992 setFeatureBits(Mips::FeatureGINV, "ginv");
6993 getTargetStreamer().emitDirectiveSetGINV();
6994 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006995 }
6996 return false;
6997}
6998
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006999bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007000 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007001 if (getLexer().isNot(AsmToken::Comma)) {
7002 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007003 return Error(Loc, ErrorStr);
7004 }
7005
Matheus Almeida2852af82014-04-22 10:15:54 +00007006 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007007 return true;
7008}
7009
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007010// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
7011// In this class, it is only used for .cprestore.
7012// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
7013// MipsTargetELFStreamer and MipsAsmParser.
7014bool MipsAsmParser::isPicAndNotNxxAbi() {
7015 return inPicMode() && !(isABI_N32() || isABI_N64());
7016}
7017
Toma Tabacuc4c202a2014-10-01 14:53:19 +00007018bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00007019 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00007020 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007021
Toma Tabacudde4c462014-11-06 10:02:45 +00007022 if (inMips16Mode()) {
7023 reportParseError(".cpload is not supported in Mips16 mode");
7024 return false;
7025 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007026
David Blaikie960ea3f2014-06-08 16:18:35 +00007027 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00007028 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007029 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7030 reportParseError("expected register containing function address");
7031 return false;
7032 }
7033
David Blaikie960ea3f2014-06-08 16:18:35 +00007034 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
7035 if (!RegOpnd.isGPRAsmReg()) {
7036 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007037 return false;
7038 }
7039
Toma Tabacudde4c462014-11-06 10:02:45 +00007040 // If this is not the end of the statement, report an error.
7041 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7042 reportParseError("unexpected token, expected end of statement");
7043 return false;
7044 }
7045
Toma Tabacuc4c202a2014-10-01 14:53:19 +00007046 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007047 return false;
7048}
7049
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007050bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
7051 MCAsmParser &Parser = getParser();
7052
7053 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
7054 // is used in non-PIC mode.
7055
7056 if (inMips16Mode()) {
7057 reportParseError(".cprestore is not supported in Mips16 mode");
7058 return false;
7059 }
7060
7061 // Get the stack offset value.
7062 const MCExpr *StackOffset;
7063 int64_t StackOffsetVal;
7064 if (Parser.parseExpression(StackOffset)) {
7065 reportParseError("expected stack offset value");
7066 return false;
7067 }
7068
7069 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
7070 reportParseError("stack offset is not an absolute expression");
7071 return false;
7072 }
7073
7074 if (StackOffsetVal < 0) {
7075 Warning(Loc, ".cprestore with negative stack offset has no effect");
7076 IsCpRestoreSet = false;
7077 } else {
7078 IsCpRestoreSet = true;
7079 CpRestoreOffset = StackOffsetVal;
7080 }
7081
7082 // If this is not the end of the statement, report an error.
7083 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7084 reportParseError("unexpected token, expected end of statement");
7085 return false;
7086 }
7087
Daniel Sandersdf8510d2016-05-11 12:48:19 +00007088 if (!getTargetStreamer().emitDirectiveCpRestore(
7089 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00007090 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007091 Parser.Lex(); // Consume the EndOfStatement.
7092 return false;
7093}
7094
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007095bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007096 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007097 unsigned FuncReg;
7098 unsigned Save;
7099 bool SaveIsReg = true;
7100
Matheus Almeida7e815762014-06-18 13:08:59 +00007101 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007102 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007103 if (ResTy == MatchOperand_NoMatch) {
7104 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00007105 return false;
7106 }
7107
7108 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7109 if (!FuncRegOpnd.isGPRAsmReg()) {
7110 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007111 return false;
7112 }
7113
7114 FuncReg = FuncRegOpnd.getGPR32Reg();
7115 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007116
Toma Tabacu65f10572014-09-16 15:00:52 +00007117 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007118 return true;
7119
Toma Tabacu13964452014-09-04 13:23:44 +00007120 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007121 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00007122 const MCExpr *OffsetExpr;
7123 int64_t OffsetVal;
7124 SMLoc ExprLoc = getLexer().getLoc();
7125
7126 if (Parser.parseExpression(OffsetExpr) ||
7127 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
7128 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00007129 return false;
7130 }
Daniel Sanders5d796282015-09-21 09:26:55 +00007131
7132 Save = OffsetVal;
7133 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00007134 } else {
7135 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7136 if (!SaveOpnd.isGPRAsmReg()) {
7137 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007138 return false;
7139 }
7140 Save = SaveOpnd.getGPR32Reg();
7141 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007142
Toma Tabacu65f10572014-09-16 15:00:52 +00007143 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007144 return true;
7145
Toma Tabacu8874eac2015-02-18 13:46:53 +00007146 const MCExpr *Expr;
7147 if (Parser.parseExpression(Expr)) {
7148 reportParseError("expected expression");
7149 return false;
7150 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007151
Toma Tabacu8874eac2015-02-18 13:46:53 +00007152 if (Expr->getKind() != MCExpr::SymbolRef) {
7153 reportParseError("expected symbol");
7154 return false;
7155 }
7156 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
7157
Daniel Sandersf173dda2015-09-22 10:50:09 +00007158 CpSaveLocation = Save;
7159 CpSaveLocationIsRegister = SaveIsReg;
7160
Toma Tabacu8874eac2015-02-18 13:46:53 +00007161 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
7162 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007163 return false;
7164}
7165
Daniel Sandersf173dda2015-09-22 10:50:09 +00007166bool MipsAsmParser::parseDirectiveCPReturn() {
7167 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
7168 CpSaveLocationIsRegister);
7169 return false;
7170}
7171
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007172bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007173 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007174 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7175 const AsmToken &Tok = Parser.getTok();
7176
7177 if (Tok.getString() == "2008") {
7178 Parser.Lex();
7179 getTargetStreamer().emitDirectiveNaN2008();
7180 return false;
7181 } else if (Tok.getString() == "legacy") {
7182 Parser.Lex();
7183 getTargetStreamer().emitDirectiveNaNLegacy();
7184 return false;
7185 }
7186 }
7187 // If we don't recognize the option passed to the .nan
7188 // directive (e.g. no option or unknown option), emit an error.
7189 reportParseError("invalid option in .nan directive");
7190 return false;
7191}
7192
Jack Carter0b744b32012-10-04 02:29:46 +00007193bool MipsAsmParser::parseDirectiveSet() {
Simon Atanasyand408ec42018-05-29 09:51:28 +00007194 const AsmToken &Tok = getParser().getTok();
7195 StringRef IdVal = Tok.getString();
7196 SMLoc Loc = Tok.getLoc();
Jack Carter0b744b32012-10-04 02:29:46 +00007197
Simon Atanasyand408ec42018-05-29 09:51:28 +00007198 if (IdVal == "noat")
Jack Carter0b744b32012-10-04 02:29:46 +00007199 return parseSetNoAtDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007200 if (IdVal == "at")
Jack Carter0b744b32012-10-04 02:29:46 +00007201 return parseSetAtDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007202 if (IdVal == "arch")
Toma Tabacu85618b32014-08-19 14:22:52 +00007203 return parseSetArchDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007204 if (IdVal == "bopt") {
7205 Warning(Loc, "'bopt' feature is unsupported");
Simon Dardisac9c30c2017-02-01 18:50:24 +00007206 getParser().Lex();
7207 return false;
Simon Atanasyand408ec42018-05-29 09:51:28 +00007208 }
7209 if (IdVal == "nobopt") {
Simon Dardisac9c30c2017-02-01 18:50:24 +00007210 // We're already running in nobopt mode, so nothing to do.
7211 getParser().Lex();
7212 return false;
Simon Atanasyand408ec42018-05-29 09:51:28 +00007213 }
7214 if (IdVal == "fp")
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007215 return parseSetFpDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007216 if (IdVal == "oddspreg")
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007217 return parseSetOddSPRegDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007218 if (IdVal == "nooddspreg")
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007219 return parseSetNoOddSPRegDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007220 if (IdVal == "pop")
Toma Tabacu9db22db2014-09-09 10:15:38 +00007221 return parseSetPopDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007222 if (IdVal == "push")
Toma Tabacu9db22db2014-09-09 10:15:38 +00007223 return parseSetPushDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007224 if (IdVal == "reorder")
Jack Carter0b744b32012-10-04 02:29:46 +00007225 return parseSetReorderDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007226 if (IdVal == "noreorder")
Jack Carter0b744b32012-10-04 02:29:46 +00007227 return parseSetNoReorderDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007228 if (IdVal == "macro")
Jack Carter0b744b32012-10-04 02:29:46 +00007229 return parseSetMacroDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007230 if (IdVal == "nomacro")
Jack Carter0b744b32012-10-04 02:29:46 +00007231 return parseSetNoMacroDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007232 if (IdVal == "mips16")
Toma Tabacucc2502d2014-11-04 17:18:07 +00007233 return parseSetMips16Directive();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007234 if (IdVal == "nomips16")
Jack Carter39536722014-01-22 23:08:42 +00007235 return parseSetNoMips16Directive();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007236 if (IdVal == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00007237 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007238 getTargetStreamer().emitDirectiveSetNoMicroMips();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007239 getParser().eatToEndOfStatement();
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007240 return false;
Simon Atanasyand408ec42018-05-29 09:51:28 +00007241 }
7242 if (IdVal == "micromips") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007243 if (hasMips64r6()) {
Simon Atanasyand408ec42018-05-29 09:51:28 +00007244 Error(Loc, ".set micromips directive is not supported with MIPS64R6");
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007245 return false;
7246 }
Matheus Almeida2852af82014-04-22 10:15:54 +00007247 return parseSetFeature(Mips::FeatureMicroMips);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007248 }
7249 if (IdVal == "mips0")
Toma Tabacu26647792014-09-09 12:52:14 +00007250 return parseSetMips0Directive();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007251 if (IdVal == "mips1")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007252 return parseSetFeature(Mips::FeatureMips1);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007253 if (IdVal == "mips2")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007254 return parseSetFeature(Mips::FeatureMips2);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007255 if (IdVal == "mips3")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007256 return parseSetFeature(Mips::FeatureMips3);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007257 if (IdVal == "mips4")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007258 return parseSetFeature(Mips::FeatureMips4);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007259 if (IdVal == "mips5")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007260 return parseSetFeature(Mips::FeatureMips5);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007261 if (IdVal == "mips32")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007262 return parseSetFeature(Mips::FeatureMips32);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007263 if (IdVal == "mips32r2")
Matheus Almeida2852af82014-04-22 10:15:54 +00007264 return parseSetFeature(Mips::FeatureMips32r2);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007265 if (IdVal == "mips32r3")
Daniel Sanders17793142015-02-18 16:24:50 +00007266 return parseSetFeature(Mips::FeatureMips32r3);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007267 if (IdVal == "mips32r5")
Daniel Sanders17793142015-02-18 16:24:50 +00007268 return parseSetFeature(Mips::FeatureMips32r5);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007269 if (IdVal == "mips32r6")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007270 return parseSetFeature(Mips::FeatureMips32r6);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007271 if (IdVal == "mips64")
Matheus Almeida2852af82014-04-22 10:15:54 +00007272 return parseSetFeature(Mips::FeatureMips64);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007273 if (IdVal == "mips64r2")
Matheus Almeida2852af82014-04-22 10:15:54 +00007274 return parseSetFeature(Mips::FeatureMips64r2);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007275 if (IdVal == "mips64r3")
Daniel Sanders17793142015-02-18 16:24:50 +00007276 return parseSetFeature(Mips::FeatureMips64r3);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007277 if (IdVal == "mips64r5")
Daniel Sanders17793142015-02-18 16:24:50 +00007278 return parseSetFeature(Mips::FeatureMips64r5);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007279 if (IdVal == "mips64r6") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007280 if (inMicroMipsMode()) {
Simon Atanasyand408ec42018-05-29 09:51:28 +00007281 Error(Loc, "MIPS64R6 is not supported with microMIPS");
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007282 return false;
7283 }
Daniel Sandersf0df2212014-08-04 12:20:00 +00007284 return parseSetFeature(Mips::FeatureMips64r6);
Jack Carter0b744b32012-10-04 02:29:46 +00007285 }
Simon Atanasyand408ec42018-05-29 09:51:28 +00007286 if (IdVal == "dsp")
7287 return parseSetFeature(Mips::FeatureDSP);
7288 if (IdVal == "dspr2")
7289 return parseSetFeature(Mips::FeatureDSPR2);
7290 if (IdVal == "nodsp")
7291 return parseSetNoDspDirective();
7292 if (IdVal == "msa")
7293 return parseSetMsaDirective();
7294 if (IdVal == "nomsa")
7295 return parseSetNoMsaDirective();
7296 if (IdVal == "mt")
7297 return parseSetMtDirective();
7298 if (IdVal == "nomt")
7299 return parseSetNoMtDirective();
7300 if (IdVal == "softfloat")
7301 return parseSetSoftFloatDirective();
7302 if (IdVal == "hardfloat")
7303 return parseSetHardFloatDirective();
7304 if (IdVal == "crc")
7305 return parseSetFeature(Mips::FeatureCRC);
7306 if (IdVal == "nocrc")
7307 return parseSetNoCRCDirective();
7308 if (IdVal == "virt")
7309 return parseSetFeature(Mips::FeatureVirt);
7310 if (IdVal == "novirt")
7311 return parseSetNoVirtDirective();
7312 if (IdVal == "ginv")
7313 return parseSetFeature(Mips::FeatureGINV);
7314 if (IdVal == "noginv")
7315 return parseSetNoGINVDirective();
Jack Carter07c818d2013-01-25 01:31:34 +00007316
Simon Atanasyand408ec42018-05-29 09:51:28 +00007317 // It is just an identifier, look for an assignment.
7318 return parseSetAssignment();
Jack Carter0b744b32012-10-04 02:29:46 +00007319}
7320
Vladimir Medic4c299852013-11-06 11:27:05 +00007321/// parseDirectiveGpWord
7322/// ::= .gpword local_sym
7323bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007324 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00007325 const MCExpr *Value;
7326 // EmitGPRel32Value requires an expression, so we are using base class
7327 // method to evaluate the expression.
7328 if (getParser().parseExpression(Value))
7329 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00007330 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00007331
Vladimir Medice10c1122013-11-13 13:18:04 +00007332 if (getLexer().isNot(AsmToken::EndOfStatement))
Fangrui Songf78650a2018-07-30 19:41:25 +00007333 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007334 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00007335 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00007336 return false;
7337}
7338
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007339/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00007340/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007341bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007342 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007343 const MCExpr *Value;
7344 // EmitGPRel64Value requires an expression, so we are using base class
7345 // method to evaluate the expression.
7346 if (getParser().parseExpression(Value))
7347 return true;
7348 getParser().getStreamer().EmitGPRel64Value(Value);
7349
7350 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007351 return Error(getLexer().getLoc(),
7352 "unexpected token, expected end of statement");
7353 Parser.Lex(); // Eat EndOfStatement token.
7354 return false;
7355}
7356
7357/// parseDirectiveDtpRelWord
7358/// ::= .dtprelword tls_sym
7359bool MipsAsmParser::parseDirectiveDtpRelWord() {
7360 MCAsmParser &Parser = getParser();
7361 const MCExpr *Value;
7362 // EmitDTPRel32Value requires an expression, so we are using base class
7363 // method to evaluate the expression.
7364 if (getParser().parseExpression(Value))
7365 return true;
7366 getParser().getStreamer().EmitDTPRel32Value(Value);
7367
7368 if (getLexer().isNot(AsmToken::EndOfStatement))
7369 return Error(getLexer().getLoc(),
7370 "unexpected token, expected end of statement");
7371 Parser.Lex(); // Eat EndOfStatement token.
7372 return false;
7373}
7374
7375/// parseDirectiveDtpRelDWord
7376/// ::= .dtpreldword tls_sym
7377bool MipsAsmParser::parseDirectiveDtpRelDWord() {
7378 MCAsmParser &Parser = getParser();
7379 const MCExpr *Value;
7380 // EmitDTPRel64Value requires an expression, so we are using base class
7381 // method to evaluate the expression.
7382 if (getParser().parseExpression(Value))
7383 return true;
7384 getParser().getStreamer().EmitDTPRel64Value(Value);
7385
7386 if (getLexer().isNot(AsmToken::EndOfStatement))
7387 return Error(getLexer().getLoc(),
7388 "unexpected token, expected end of statement");
7389 Parser.Lex(); // Eat EndOfStatement token.
7390 return false;
7391}
7392
7393/// parseDirectiveTpRelWord
7394/// ::= .tprelword tls_sym
7395bool MipsAsmParser::parseDirectiveTpRelWord() {
7396 MCAsmParser &Parser = getParser();
7397 const MCExpr *Value;
7398 // EmitTPRel32Value requires an expression, so we are using base class
7399 // method to evaluate the expression.
7400 if (getParser().parseExpression(Value))
7401 return true;
7402 getParser().getStreamer().EmitTPRel32Value(Value);
7403
7404 if (getLexer().isNot(AsmToken::EndOfStatement))
7405 return Error(getLexer().getLoc(),
7406 "unexpected token, expected end of statement");
7407 Parser.Lex(); // Eat EndOfStatement token.
7408 return false;
7409}
7410
7411/// parseDirectiveTpRelDWord
7412/// ::= .tpreldword tls_sym
7413bool MipsAsmParser::parseDirectiveTpRelDWord() {
7414 MCAsmParser &Parser = getParser();
7415 const MCExpr *Value;
7416 // EmitTPRel64Value requires an expression, so we are using base class
7417 // method to evaluate the expression.
7418 if (getParser().parseExpression(Value))
7419 return true;
7420 getParser().getStreamer().EmitTPRel64Value(Value);
7421
7422 if (getLexer().isNot(AsmToken::EndOfStatement))
7423 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007424 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00007425 Parser.Lex(); // Eat EndOfStatement token.
7426 return false;
7427}
7428
Jack Carter0cd3c192014-01-06 23:27:31 +00007429bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007430 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00007431 // Get the option token.
7432 AsmToken Tok = Parser.getTok();
7433 // At the moment only identifiers are supported.
7434 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007435 return Error(Parser.getTok().getLoc(),
7436 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00007437 }
7438
7439 StringRef Option = Tok.getIdentifier();
7440
7441 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007442 // MipsAsmParser needs to know if the current PIC mode changes.
7443 IsPicEnabled = false;
7444
Jack Carter0cd3c192014-01-06 23:27:31 +00007445 getTargetStreamer().emitDirectiveOptionPic0();
7446 Parser.Lex();
7447 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007448 return Error(Parser.getTok().getLoc(),
7449 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007450 }
7451 return false;
7452 }
7453
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007454 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007455 // MipsAsmParser needs to know if the current PIC mode changes.
7456 IsPicEnabled = true;
7457
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007458 getTargetStreamer().emitDirectiveOptionPic2();
7459 Parser.Lex();
7460 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007461 return Error(Parser.getTok().getLoc(),
7462 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007463 }
7464 return false;
7465 }
7466
Jack Carter0cd3c192014-01-06 23:27:31 +00007467 // Unknown option.
Fangrui Songf78650a2018-07-30 19:41:25 +00007468 Warning(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007469 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007470 Parser.eatToEndOfStatement();
7471 return false;
7472}
7473
Toma Tabacu9ca50962015-04-16 09:53:47 +00007474/// parseInsnDirective
7475/// ::= .insn
7476bool MipsAsmParser::parseInsnDirective() {
7477 // If this is not the end of the statement, report an error.
7478 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7479 reportParseError("unexpected token, expected end of statement");
7480 return false;
7481 }
7482
7483 // The actual label marking happens in
7484 // MipsELFStreamer::createPendingLabelRelocs().
7485 getTargetStreamer().emitDirectiveInsn();
7486
7487 getParser().Lex(); // Eat EndOfStatement token.
7488 return false;
7489}
7490
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007491/// parseRSectionDirective
7492/// ::= .rdata
7493bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
7494 // If this is not the end of the statement, report an error.
7495 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7496 reportParseError("unexpected token, expected end of statement");
7497 return false;
7498 }
7499
7500 MCSection *ELFSection = getContext().getELFSection(
7501 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7502 getParser().getStreamer().SwitchSection(ELFSection);
7503
7504 getParser().Lex(); // Eat EndOfStatement token.
7505 return false;
7506}
7507
Simon Atanasyanbe186202016-02-11 06:45:54 +00007508/// parseSSectionDirective
7509/// ::= .sbss
7510/// ::= .sdata
7511bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7512 // If this is not the end of the statement, report an error.
7513 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7514 reportParseError("unexpected token, expected end of statement");
7515 return false;
7516 }
7517
7518 MCSection *ELFSection = getContext().getELFSection(
7519 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7520 getParser().getStreamer().SwitchSection(ELFSection);
7521
7522 getParser().Lex(); // Eat EndOfStatement token.
7523 return false;
7524}
7525
Daniel Sanders7e527422014-07-10 13:38:23 +00007526/// parseDirectiveModule
7527/// ::= .module oddspreg
7528/// ::= .module nooddspreg
7529/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007530/// ::= .module softfloat
7531/// ::= .module hardfloat
Simon Dardis805f1e02017-07-11 21:28:36 +00007532/// ::= .module mt
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007533/// ::= .module crc
7534/// ::= .module nocrc
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007535/// ::= .module virt
7536/// ::= .module novirt
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007537/// ::= .module ginv
7538/// ::= .module noginv
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007539bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007540 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007541 MCAsmLexer &Lexer = getLexer();
7542 SMLoc L = Lexer.getLoc();
7543
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007544 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007545 // TODO : get a better message.
7546 reportParseError(".module directive must appear before any code");
7547 return false;
7548 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007549
Toma Tabacuc405c822015-01-23 10:40:19 +00007550 StringRef Option;
7551 if (Parser.parseIdentifier(Option)) {
7552 reportParseError("expected .module option identifier");
7553 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007554 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007555
Toma Tabacuc405c822015-01-23 10:40:19 +00007556 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007557 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007558
Toma Tabacu3c499582015-06-25 10:56:57 +00007559 // Synchronize the abiflags information with the FeatureBits information we
7560 // changed above.
7561 getTargetStreamer().updateABIInfo(*this);
7562
7563 // If printing assembly, use the recently updated abiflags information.
7564 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7565 // emitted at the end).
7566 getTargetStreamer().emitDirectiveModuleOddSPReg();
7567
Toma Tabacuc405c822015-01-23 10:40:19 +00007568 // If this is not the end of the statement, report an error.
7569 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7570 reportParseError("unexpected token, expected end of statement");
7571 return false;
7572 }
7573
7574 return false; // parseDirectiveModule has finished successfully.
7575 } else if (Option == "nooddspreg") {
7576 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007577 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007578 }
7579
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007580 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007581
Toma Tabacu3c499582015-06-25 10:56:57 +00007582 // Synchronize the abiflags information with the FeatureBits information we
7583 // changed above.
7584 getTargetStreamer().updateABIInfo(*this);
7585
7586 // If printing assembly, use the recently updated abiflags information.
7587 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7588 // emitted at the end).
7589 getTargetStreamer().emitDirectiveModuleOddSPReg();
7590
Toma Tabacuc405c822015-01-23 10:40:19 +00007591 // If this is not the end of the statement, report an error.
7592 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7593 reportParseError("unexpected token, expected end of statement");
7594 return false;
7595 }
7596
7597 return false; // parseDirectiveModule has finished successfully.
7598 } else if (Option == "fp") {
7599 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007600 } else if (Option == "softfloat") {
7601 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7602
7603 // Synchronize the ABI Flags information with the FeatureBits information we
7604 // updated above.
7605 getTargetStreamer().updateABIInfo(*this);
7606
7607 // If printing assembly, use the recently updated ABI Flags information.
7608 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7609 // emitted later).
7610 getTargetStreamer().emitDirectiveModuleSoftFloat();
7611
7612 // If this is not the end of the statement, report an error.
7613 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7614 reportParseError("unexpected token, expected end of statement");
7615 return false;
7616 }
7617
7618 return false; // parseDirectiveModule has finished successfully.
7619 } else if (Option == "hardfloat") {
7620 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7621
7622 // Synchronize the ABI Flags information with the FeatureBits information we
7623 // updated above.
7624 getTargetStreamer().updateABIInfo(*this);
7625
7626 // If printing assembly, use the recently updated ABI Flags information.
7627 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7628 // emitted later).
7629 getTargetStreamer().emitDirectiveModuleHardFloat();
7630
7631 // If this is not the end of the statement, report an error.
7632 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7633 reportParseError("unexpected token, expected end of statement");
7634 return false;
7635 }
7636
7637 return false; // parseDirectiveModule has finished successfully.
Simon Dardis805f1e02017-07-11 21:28:36 +00007638 } else if (Option == "mt") {
7639 setModuleFeatureBits(Mips::FeatureMT, "mt");
7640
7641 // Synchronize the ABI Flags information with the FeatureBits information we
7642 // updated above.
7643 getTargetStreamer().updateABIInfo(*this);
7644
Simon Dardisd9611922017-07-11 21:36:58 +00007645 // If printing assembly, use the recently updated ABI Flags information.
Simon Dardis805f1e02017-07-11 21:28:36 +00007646 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7647 // emitted later).
7648 getTargetStreamer().emitDirectiveModuleMT();
7649
7650 // If this is not the end of the statement, report an error.
7651 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7652 reportParseError("unexpected token, expected end of statement");
7653 return false;
7654 }
7655
7656 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007657 } else if (Option == "crc") {
7658 setModuleFeatureBits(Mips::FeatureCRC, "crc");
7659
7660 // Synchronize the ABI Flags information with the FeatureBits information we
7661 // updated above.
7662 getTargetStreamer().updateABIInfo(*this);
7663
7664 // If printing assembly, use the recently updated ABI Flags information.
7665 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7666 // emitted later).
7667 getTargetStreamer().emitDirectiveModuleCRC();
7668
7669 // If this is not the end of the statement, report an error.
7670 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7671 reportParseError("unexpected token, expected end of statement");
7672 return false;
7673 }
7674
7675 return false; // parseDirectiveModule has finished successfully.
7676 } else if (Option == "nocrc") {
7677 clearModuleFeatureBits(Mips::FeatureCRC, "crc");
7678
7679 // Synchronize the ABI Flags information with the FeatureBits information we
7680 // updated above.
7681 getTargetStreamer().updateABIInfo(*this);
7682
7683 // If printing assembly, use the recently updated ABI Flags information.
7684 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7685 // emitted later).
7686 getTargetStreamer().emitDirectiveModuleNoCRC();
7687
7688 // If this is not the end of the statement, report an error.
7689 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7690 reportParseError("unexpected token, expected end of statement");
7691 return false;
7692 }
7693
7694 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007695 } else if (Option == "virt") {
7696 setModuleFeatureBits(Mips::FeatureVirt, "virt");
7697
7698 // Synchronize the ABI Flags information with the FeatureBits information we
7699 // updated above.
7700 getTargetStreamer().updateABIInfo(*this);
7701
7702 // If printing assembly, use the recently updated ABI Flags information.
7703 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7704 // emitted later).
7705 getTargetStreamer().emitDirectiveModuleVirt();
7706
7707 // If this is not the end of the statement, report an error.
7708 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7709 reportParseError("unexpected token, expected end of statement");
7710 return false;
7711 }
7712
7713 return false; // parseDirectiveModule has finished successfully.
7714 } else if (Option == "novirt") {
7715 clearModuleFeatureBits(Mips::FeatureVirt, "virt");
7716
7717 // Synchronize the ABI Flags information with the FeatureBits information we
7718 // updated above.
7719 getTargetStreamer().updateABIInfo(*this);
7720
7721 // If printing assembly, use the recently updated ABI Flags information.
7722 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7723 // emitted later).
7724 getTargetStreamer().emitDirectiveModuleNoVirt();
7725
7726 // If this is not the end of the statement, report an error.
7727 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7728 reportParseError("unexpected token, expected end of statement");
7729 return false;
7730 }
7731
7732 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007733 } else if (Option == "ginv") {
7734 setModuleFeatureBits(Mips::FeatureGINV, "ginv");
7735
7736 // Synchronize the ABI Flags information with the FeatureBits information we
7737 // updated above.
7738 getTargetStreamer().updateABIInfo(*this);
7739
7740 // If printing assembly, use the recently updated ABI Flags information.
7741 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7742 // emitted later).
7743 getTargetStreamer().emitDirectiveModuleGINV();
7744
7745 // If this is not the end of the statement, report an error.
7746 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7747 reportParseError("unexpected token, expected end of statement");
7748 return false;
7749 }
7750
7751 return false; // parseDirectiveModule has finished successfully.
7752 } else if (Option == "noginv") {
7753 clearModuleFeatureBits(Mips::FeatureGINV, "ginv");
7754
7755 // Synchronize the ABI Flags information with the FeatureBits information we
7756 // updated above.
7757 getTargetStreamer().updateABIInfo(*this);
7758
7759 // If printing assembly, use the recently updated ABI Flags information.
7760 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7761 // emitted later).
7762 getTargetStreamer().emitDirectiveModuleNoGINV();
7763
7764 // If this is not the end of the statement, report an error.
7765 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7766 reportParseError("unexpected token, expected end of statement");
7767 return false;
7768 }
7769
7770 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007771 } else {
7772 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7773 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007774}
7775
7776/// parseDirectiveModuleFP
7777/// ::= =32
7778/// ::= =xx
7779/// ::= =64
7780bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007781 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007782 MCAsmLexer &Lexer = getLexer();
7783
7784 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007785 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007786 return false;
7787 }
7788 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007789
Daniel Sanders7e527422014-07-10 13:38:23 +00007790 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007791 if (!parseFpABIValue(FpABI, ".module"))
7792 return false;
7793
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007794 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007795 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007796 return false;
7797 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007798
Toma Tabacua64e5402015-06-25 12:44:38 +00007799 // Synchronize the abiflags information with the FeatureBits information we
7800 // changed above.
7801 getTargetStreamer().updateABIInfo(*this);
7802
7803 // If printing assembly, use the recently updated abiflags information.
7804 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7805 // emitted at the end).
7806 getTargetStreamer().emitDirectiveModuleFP();
7807
Daniel Sanders7e527422014-07-10 13:38:23 +00007808 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007809 return false;
7810}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007811
Daniel Sanders7e527422014-07-10 13:38:23 +00007812bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007813 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007814 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007815 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007816 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007817
7818 if (Lexer.is(AsmToken::Identifier)) {
7819 StringRef Value = Parser.getTok().getString();
7820 Parser.Lex();
7821
7822 if (Value != "xx") {
7823 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7824 return false;
7825 }
7826
7827 if (!isABI_O32()) {
7828 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7829 return false;
7830 }
7831
Daniel Sanders7e527422014-07-10 13:38:23 +00007832 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007833 if (ModuleLevelOptions) {
7834 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7835 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7836 } else {
7837 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7838 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7839 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007840 return true;
7841 }
7842
7843 if (Lexer.is(AsmToken::Integer)) {
7844 unsigned Value = Parser.getTok().getIntVal();
7845 Parser.Lex();
7846
7847 if (Value != 32 && Value != 64) {
7848 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7849 return false;
7850 }
7851
7852 if (Value == 32) {
7853 if (!isABI_O32()) {
7854 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7855 return false;
7856 }
7857
Daniel Sanders7e527422014-07-10 13:38:23 +00007858 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007859 if (ModuleLevelOptions) {
7860 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7861 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7862 } else {
7863 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7864 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7865 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007866 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007867 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007868 if (ModuleLevelOptions) {
7869 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7870 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7871 } else {
7872 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7873 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7874 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007875 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007876
Daniel Sanders7e527422014-07-10 13:38:23 +00007877 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007878 }
7879
7880 return false;
7881}
7882
Jack Carter0b744b32012-10-04 02:29:46 +00007883bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007884 // This returns false if this function recognizes the directive
7885 // regardless of whether it is successfully handles or reports an
7886 // error. Otherwise it returns true to give the generic parser a
7887 // chance at recognizing it.
7888
Rafael Espindola961d4692014-11-11 05:18:41 +00007889 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007890 StringRef IDVal = DirectiveID.getString();
7891
Nirav Dave996fc132016-05-05 14:15:46 +00007892 if (IDVal == ".cpload") {
7893 parseDirectiveCpLoad(DirectiveID.getLoc());
7894 return false;
7895 }
7896 if (IDVal == ".cprestore") {
7897 parseDirectiveCpRestore(DirectiveID.getLoc());
7898 return false;
7899 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007900 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007901 StringRef SymbolName;
7902
7903 if (Parser.parseIdentifier(SymbolName)) {
7904 reportParseError("expected identifier after .ent");
7905 return false;
7906 }
7907
7908 // There's an undocumented extension that allows an integer to
7909 // follow the name of the procedure which AFAICS is ignored by GAS.
7910 // Example: .ent foo,2
7911 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7912 if (getLexer().isNot(AsmToken::Comma)) {
7913 // Even though we accept this undocumented extension for compatibility
7914 // reasons, the additional integer argument does not actually change
7915 // the behaviour of the '.ent' directive, so we would like to discourage
7916 // its use. We do this by not referring to the extended version in
7917 // error messages which are not directly related to its use.
7918 reportParseError("unexpected token, expected end of statement");
7919 return false;
7920 }
7921 Parser.Lex(); // Eat the comma.
7922 const MCExpr *DummyNumber;
7923 int64_t DummyNumberVal;
7924 // If the user was explicitly trying to use the extended version,
7925 // we still give helpful extension-related error messages.
7926 if (Parser.parseExpression(DummyNumber)) {
7927 reportParseError("expected number after comma");
7928 return false;
7929 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007930 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007931 reportParseError("expected an absolute expression after comma");
7932 return false;
7933 }
7934 }
7935
7936 // If this is not the end of the statement, report an error.
7937 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7938 reportParseError("unexpected token, expected end of statement");
7939 return false;
7940 }
7941
Jim Grosbach6f482002015-05-18 18:43:14 +00007942 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007943
7944 getTargetStreamer().emitDirectiveEnt(*Sym);
7945 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007946 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007947 return false;
7948 }
7949
Jack Carter07c818d2013-01-25 01:31:34 +00007950 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007951 StringRef SymbolName;
7952
7953 if (Parser.parseIdentifier(SymbolName)) {
7954 reportParseError("expected identifier after .end");
7955 return false;
7956 }
7957
7958 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7959 reportParseError("unexpected token, expected end of statement");
7960 return false;
7961 }
7962
7963 if (CurrentFn == nullptr) {
7964 reportParseError(".end used without .ent");
7965 return false;
7966 }
7967
7968 if ((SymbolName != CurrentFn->getName())) {
7969 reportParseError(".end symbol does not match .ent symbol");
7970 return false;
7971 }
7972
7973 getTargetStreamer().emitDirectiveEnd(SymbolName);
7974 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007975 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007976 return false;
7977 }
7978
Jack Carter07c818d2013-01-25 01:31:34 +00007979 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007980 // .frame $stack_reg, frame_size_in_bytes, $return_reg
7981 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007982 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007983 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7984 reportParseError("expected stack register");
7985 return false;
7986 }
7987
7988 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7989 if (!StackRegOpnd.isGPRAsmReg()) {
7990 reportParseError(StackRegOpnd.getStartLoc(),
7991 "expected general purpose register");
7992 return false;
7993 }
7994 unsigned StackReg = StackRegOpnd.getGPR32Reg();
7995
7996 if (Parser.getTok().is(AsmToken::Comma))
7997 Parser.Lex();
7998 else {
7999 reportParseError("unexpected token, expected comma");
8000 return false;
8001 }
8002
8003 // Parse the frame size.
8004 const MCExpr *FrameSize;
8005 int64_t FrameSizeVal;
8006
8007 if (Parser.parseExpression(FrameSize)) {
8008 reportParseError("expected frame size value");
8009 return false;
8010 }
8011
Jim Grosbach13760bd2015-05-30 01:25:56 +00008012 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008013 reportParseError("frame size not an absolute expression");
8014 return false;
8015 }
8016
8017 if (Parser.getTok().is(AsmToken::Comma))
8018 Parser.Lex();
8019 else {
8020 reportParseError("unexpected token, expected comma");
8021 return false;
8022 }
8023
8024 // Parse the return register.
8025 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00008026 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00008027 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
8028 reportParseError("expected return register");
8029 return false;
8030 }
8031
8032 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
8033 if (!ReturnRegOpnd.isGPRAsmReg()) {
8034 reportParseError(ReturnRegOpnd.getStartLoc(),
8035 "expected general purpose register");
8036 return false;
8037 }
8038
8039 // If this is not the end of the statement, report an error.
8040 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8041 reportParseError("unexpected token, expected end of statement");
8042 return false;
8043 }
8044
8045 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
8046 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00008047 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00008048 return false;
8049 }
8050
Jack Carter07c818d2013-01-25 01:31:34 +00008051 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00008052 parseDirectiveSet();
8053 return false;
Jack Carterbe332172012-09-07 00:48:02 +00008054 }
8055
Daniel Sandersd97a6342014-08-13 10:07:34 +00008056 if (IDVal == ".mask" || IDVal == ".fmask") {
8057 // .mask bitmask, frame_offset
8058 // bitmask: One bit for each register used.
8059 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
8060 // first register is expected to be saved.
8061 // Examples:
8062 // .mask 0x80000000, -4
8063 // .fmask 0x80000000, -4
8064 //
Jack Carterbe332172012-09-07 00:48:02 +00008065
Daniel Sandersd97a6342014-08-13 10:07:34 +00008066 // Parse the bitmask
8067 const MCExpr *BitMask;
8068 int64_t BitMaskVal;
8069
8070 if (Parser.parseExpression(BitMask)) {
8071 reportParseError("expected bitmask value");
8072 return false;
8073 }
8074
Jim Grosbach13760bd2015-05-30 01:25:56 +00008075 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008076 reportParseError("bitmask not an absolute expression");
8077 return false;
8078 }
8079
8080 if (Parser.getTok().is(AsmToken::Comma))
8081 Parser.Lex();
8082 else {
8083 reportParseError("unexpected token, expected comma");
8084 return false;
8085 }
8086
8087 // Parse the frame_offset
8088 const MCExpr *FrameOffset;
8089 int64_t FrameOffsetVal;
8090
8091 if (Parser.parseExpression(FrameOffset)) {
8092 reportParseError("expected frame offset value");
8093 return false;
8094 }
8095
Jim Grosbach13760bd2015-05-30 01:25:56 +00008096 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008097 reportParseError("frame offset not an absolute expression");
8098 return false;
8099 }
8100
8101 // If this is not the end of the statement, report an error.
8102 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8103 reportParseError("unexpected token, expected end of statement");
8104 return false;
8105 }
8106
8107 if (IDVal == ".mask")
8108 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
8109 else
8110 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00008111 return false;
8112 }
8113
Matheus Almeida0051f2d2014-04-16 15:48:55 +00008114 if (IDVal == ".nan")
8115 return parseDirectiveNaN();
8116
Jack Carter07c818d2013-01-25 01:31:34 +00008117 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00008118 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00008119 return false;
8120 }
8121
Rafael Espindolab59fb732014-03-28 18:50:26 +00008122 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00008123 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00008124 return false;
8125 }
8126
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00008127 if (IDVal == ".dtprelword") {
8128 parseDirectiveDtpRelWord();
8129 return false;
8130 }
8131
8132 if (IDVal == ".dtpreldword") {
8133 parseDirectiveDtpRelDWord();
8134 return false;
8135 }
8136
8137 if (IDVal == ".tprelword") {
8138 parseDirectiveTpRelWord();
8139 return false;
8140 }
8141
8142 if (IDVal == ".tpreldword") {
8143 parseDirectiveTpRelDWord();
8144 return false;
8145 }
8146
Nirav Dave996fc132016-05-05 14:15:46 +00008147 if (IDVal == ".option") {
8148 parseDirectiveOption();
8149 return false;
8150 }
Jack Carter0cd3c192014-01-06 23:27:31 +00008151
8152 if (IDVal == ".abicalls") {
8153 getTargetStreamer().emitDirectiveAbiCalls();
8154 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Fangrui Songf78650a2018-07-30 19:41:25 +00008155 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00008156 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00008157 }
8158 return false;
8159 }
8160
Nirav Dave996fc132016-05-05 14:15:46 +00008161 if (IDVal == ".cpsetup") {
8162 parseDirectiveCPSetup();
8163 return false;
8164 }
8165 if (IDVal == ".cpreturn") {
8166 parseDirectiveCPReturn();
8167 return false;
8168 }
8169 if (IDVal == ".module") {
8170 parseDirectiveModule();
8171 return false;
8172 }
8173 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
8174 parseInternalDirectiveReallowModule();
8175 return false;
8176 }
8177 if (IDVal == ".insn") {
8178 parseInsnDirective();
8179 return false;
8180 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00008181 if (IDVal == ".rdata") {
8182 parseRSectionDirective(".rodata");
8183 return false;
8184 }
Nirav Dave996fc132016-05-05 14:15:46 +00008185 if (IDVal == ".sbss") {
8186 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
8187 return false;
8188 }
8189 if (IDVal == ".sdata") {
8190 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
8191 return false;
8192 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00008193
Rafael Espindola870c4e92012-01-11 03:56:41 +00008194 return true;
8195}
8196
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00008197bool MipsAsmParser::parseInternalDirectiveReallowModule() {
8198 // If this is not the end of the statement, report an error.
8199 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8200 reportParseError("unexpected token, expected end of statement");
8201 return false;
8202 }
8203
8204 getTargetStreamer().reallowModuleDirective();
8205
8206 getParser().Lex(); // Eat EndOfStatement token.
8207 return false;
8208}
8209
Rafael Espindola870c4e92012-01-11 03:56:41 +00008210extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00008211 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
8212 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
8213 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
8214 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00008215}
Jack Carterb4dbc172012-09-05 23:34:03 +00008216
8217#define GET_REGISTER_MATCHER
8218#define GET_MATCHER_IMPLEMENTATION
Simon Atanasyanc49da2e2018-09-13 08:38:03 +00008219#define GET_MNEMONIC_SPELL_CHECKER
Jack Carterb4dbc172012-09-05 23:34:03 +00008220#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00008221
8222bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
8223 // Find the appropriate table for this asm variant.
8224 const MatchEntry *Start, *End;
8225 switch (VariantID) {
8226 default: llvm_unreachable("invalid variant!");
8227 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
8228 }
8229 // Search the table.
8230 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
8231 return MnemonicRange.first != MnemonicRange.second;
8232}