blob: d0fe076c4b43252703560fd52da4d9df923f0edb [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
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Daniel Sandersa6994442015-08-18 12:33:54 +000014#include "MipsTargetObjectFile.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Hrvoje Vargadbe4d962016-09-08 07:41:43 +000016#include "MCTargetDesc/MipsBaseInfo.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000017#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000022#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000023#include "llvm/MC/MCParser/MCAsmLexer.h"
24#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000025#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000026#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000027#include "llvm/MC/MCStreamer.h"
28#include "llvm/MC/MCSubtargetInfo.h"
29#include "llvm/MC/MCSymbol.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000030#include "llvm/Support/Debug.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000031#include "llvm/Support/ELF.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000032#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000033#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000034#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000035#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000036#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000037
38using namespace llvm;
39
Chandler Carruthe96dd892014-04-21 22:55:11 +000040#define DEBUG_TYPE "mips-asm-parser"
41
Joey Gouly0e76fa72013-09-12 10:28:05 +000042namespace llvm {
43class MCInstrInfo;
44}
45
Rafael Espindola870c4e92012-01-11 03:56:41 +000046namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000047class MipsAssemblerOptions {
48public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000049 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000050 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000051
Toma Tabacu9db22db2014-09-09 10:15:38 +000052 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000053 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000054 Reorder = Opts->isReorder();
55 Macro = Opts->isMacro();
56 Features = Opts->getFeatures();
57 }
58
Toma Tabacub19cf202015-04-27 13:12:59 +000059 unsigned getATRegIndex() const { return ATReg; }
60 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000061 if (Reg > 31)
62 return false;
63
64 ATReg = Reg;
65 return true;
66 }
Jack Carter0b744b32012-10-04 02:29:46 +000067
Toma Tabacu9db22db2014-09-09 10:15:38 +000068 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000069 void setReorder() { Reorder = true; }
70 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000071
Toma Tabacu9db22db2014-09-09 10:15:38 +000072 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000073 void setMacro() { Macro = true; }
74 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000075
Toma Tabacu465acfd2015-06-09 13:33:26 +000076 const FeatureBitset &getFeatures() const { return Features; }
77 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000078
Daniel Sandersf0df2212014-08-04 12:20:00 +000079 // Set of features that are either architecture features or referenced
80 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
81 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
82 // The reason we need this mask is explained in the selectArch function.
83 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000084 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000085
Jack Carter0b744b32012-10-04 02:29:46 +000086private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000087 unsigned ATReg;
88 bool Reorder;
89 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000090 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000091};
92}
93
Michael Kupersteindb0712f2015-05-26 10:47:10 +000094const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
95 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
96 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
97 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
98 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
99 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
100 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
101 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
102 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
103};
104
Jack Carter0b744b32012-10-04 02:29:46 +0000105namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000106class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000107 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000108 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000109 return static_cast<MipsTargetStreamer &>(TS);
110 }
111
Eric Christophera5762812015-01-26 17:33:46 +0000112 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000113 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000114 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
115 // nullptr, which indicates that no function is currently
116 // selected. This usually happens after an '.end func'
117 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000118 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000119 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000120 bool IsCpRestoreSet;
121 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000122 unsigned CpSaveLocation;
123 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
124 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000125
Daniel Sandersef638fe2014-10-03 15:37:37 +0000126 // Print a warning along with its fix-it message at the given range.
127 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
128 SMRange Range, bool ShowColors = true);
129
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000130#define GET_ASSEMBLER_HEADER
131#include "MipsGenAsmMatcher.inc"
132
Daniel Sandersc5537422016-07-27 13:49:44 +0000133 unsigned
134 checkEarlyTargetMatchPredicate(MCInst &Inst,
135 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000136 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
137
Chad Rosier49963552012-10-13 00:26:04 +0000138 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000139 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000140 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000141 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000142
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000143 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000144 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000145
Toma Tabacu13964452014-09-04 13:23:44 +0000146 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000147
Toma Tabacu13964452014-09-04 13:23:44 +0000148 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000149
David Blaikie960ea3f2014-06-08 16:18:35 +0000150 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
151 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000152
Craig Topper56c590a2014-04-29 07:58:02 +0000153 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000154
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000155 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
156 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000157 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000158 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000159 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
160 SMLoc S);
161 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
162 OperandMatchResultTy parseImm(OperandVector &Operands);
163 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
164 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000165 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
166 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
167 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000168
David Blaikie960ea3f2014-06-08 16:18:35 +0000169 bool searchSymbolAlias(OperandVector &Operands);
170
Toma Tabacu13964452014-09-04 13:23:44 +0000171 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000172
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000173 enum MacroExpanderResultTy {
174 MER_NotAMacro,
175 MER_Success,
176 MER_Fail,
177 };
Jack Carter30a59822012-10-04 04:03:53 +0000178
Matheus Almeida3813d572014-06-19 14:39:14 +0000179 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000180 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
181 MCStreamer &Out,
182 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000183
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000184 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
185 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000186
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000187 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000188 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000189 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000190
Toma Tabacuf712ede2015-06-17 14:31:51 +0000191 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
192 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000193 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000194
Toma Tabacu00e98672015-05-01 12:19:27 +0000195 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000196 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000197
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000198 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
199 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000200 SMLoc IDLoc, MCStreamer &Out,
201 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000202
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000203 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
204 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000205
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000206 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000207 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
208
209 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
210 const MCSubtargetInfo *STI, bool IsImmOpnd);
211
212 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
213 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000214
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000215 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
216 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000217
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
219 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000220
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000221 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
222 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000223
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000224 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
225 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000226
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000227 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
228 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000229 const bool Signed);
230
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000231 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000232 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000233
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000234 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000236
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000237 bool expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
238 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000239
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000240 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000241 MCStreamer &Out, const MCSubtargetInfo *STI);
242 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
243 const MCSubtargetInfo *STI);
244 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
245 const MCSubtargetInfo *STI);
246 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000248
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000249 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
250 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000251
Simon Dardisaff4d142016-10-18 14:28:00 +0000252 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
253 const MCSubtargetInfo *STI, bool IsLoad);
254
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000255 bool reportParseError(Twine ErrorMsg);
256 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000257
Jack Carterb5cf5902013-04-17 00:18:04 +0000258 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000259
260 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000261 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000262 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000263 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000264 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000265 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000266 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000267 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000268 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000269 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000270 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000271 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000272 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000273 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000274
275 bool parseSetAtDirective();
276 bool parseSetNoAtDirective();
277 bool parseSetMacroDirective();
278 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000279 bool parseSetMsaDirective();
280 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000281 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000282 bool parseSetReorderDirective();
283 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000284 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000285 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000286 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000287 bool parseSetOddSPRegDirective();
288 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000289 bool parseSetPopDirective();
290 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000291 bool parseSetSoftFloatDirective();
292 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000293
Jack Carterd76b2372013-03-21 21:44:16 +0000294 bool parseSetAssignment();
295
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000296 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000297 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000298 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000299 bool parseDirectiveDtpRelWord();
300 bool parseDirectiveDtpRelDWord();
301 bool parseDirectiveTpRelWord();
302 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000303 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000304 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000305 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
306 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000307
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000308 bool parseInternalDirectiveReallowModule();
309
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000310 bool eatComma(StringRef ErrorStr);
311
Jack Carter1ac53222013-02-20 23:11:17 +0000312 int matchCPURegisterName(StringRef Symbol);
313
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000314 int matchHWRegsRegisterName(StringRef Symbol);
315
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000316 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000317
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000318 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000319
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000320 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000321
Jack Carter5dc8ac92013-09-25 23:50:44 +0000322 int matchMSA128RegisterName(StringRef Name);
323
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000324 int matchMSA128CtrlRegisterName(StringRef Name);
325
Jack Carterd0bd6422013-04-18 00:41:53 +0000326 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000327
Toma Tabacu89a712b2015-04-15 10:48:56 +0000328 /// Returns the internal register number for the current AT. Also checks if
329 /// the current AT is unavailable (set to $0) and gives an error if it is.
330 /// This should be used in pseudo-instruction expansions which need AT.
331 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000332
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000333 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
334 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000335
336 // Helper function that checks if the value of a vector index is within the
337 // boundaries of accepted values for each RegisterKind
338 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
339 bool validateMSAIndex(int Val, int RegKind);
340
Daniel Sandersf0df2212014-08-04 12:20:00 +0000341 // Selects a new architecture by updating the FeatureBits with the necessary
342 // info including implied dependencies.
343 // Internally, it clears all the feature bits related to *any* architecture
344 // and selects the new one using the ToggleFeature functionality of the
345 // MCSubtargetInfo object that handles implied dependencies. The reason we
346 // clear all the arch related bits manually is because ToggleFeature only
347 // clears the features that imply the feature being cleared and not the
348 // features implied by the feature being cleared. This is easier to see
349 // with an example:
350 // --------------------------------------------------
351 // | Feature | Implies |
352 // | -------------------------------------------------|
353 // | FeatureMips1 | None |
354 // | FeatureMips2 | FeatureMips1 |
355 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
356 // | FeatureMips4 | FeatureMips3 |
357 // | ... | |
358 // --------------------------------------------------
359 //
360 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
361 // FeatureMipsGP64 | FeatureMips1)
362 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
363 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000364 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000365 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000366 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
367 STI.setFeatureBits(FeatureBits);
368 setAvailableFeatures(
369 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000370 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000371 }
372
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000373 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000374 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000375 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000376 setAvailableFeatures(
377 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000378 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000379 }
380 }
381
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000382 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000383 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000384 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000385 setAvailableFeatures(
386 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000387 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000388 }
389 }
390
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000391 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
392 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000393 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000394 }
395
396 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
397 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000398 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000399 }
400
Rafael Espindola870c4e92012-01-11 03:56:41 +0000401public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000402 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000403 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000404 Match_RequiresDifferentOperands,
405 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000406 Match_RequiresSameSrcAndDst,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000407#define GET_OPERAND_DIAGNOSTIC_TYPES
408#include "MipsGenAsmMatcher.inc"
409#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000410 };
411
Akira Hatanakab11ef082015-11-14 06:35:56 +0000412 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000413 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000414 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000415 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
416 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000417 MCAsmParserExtension::Initialize(parser);
418
Toma Tabacu11e14a92015-04-21 11:50:52 +0000419 parser.addAliasForDirective(".asciiz", ".asciz");
420
Jack Carterb4dbc172012-09-05 23:34:03 +0000421 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000422 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000423
Toma Tabacu9db22db2014-09-09 10:15:38 +0000424 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000425 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000426 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000427
Toma Tabacu9db22db2014-09-09 10:15:38 +0000428 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000429 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000430 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000431
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000432 getTargetStreamer().updateABIInfo(*this);
433
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000434 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000435 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000436
437 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000438
Rafael Espindola699281c2016-05-18 11:58:50 +0000439 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000440
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000441 IsCpRestoreSet = false;
442 CpRestoreOffset = -1;
443
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000444 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000445 if ((TheTriple.getArch() == Triple::mips) ||
446 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000447 IsLittleEndian = false;
448 else
449 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000450 }
451
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000452 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
453 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
454
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000455 bool isGP64bit() const {
456 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
457 }
458 bool isFP64bit() const {
459 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
460 }
Eric Christophera5762812015-01-26 17:33:46 +0000461 const MipsABIInfo &getABI() const { return ABI; }
462 bool isABI_N32() const { return ABI.IsN32(); }
463 bool isABI_N64() const { return ABI.IsN64(); }
464 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000465 bool isABI_FPXX() const {
466 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
467 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000468
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000469 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000470 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000471 }
472
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000473 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000474 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000475 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000476 bool hasMips1() const {
477 return getSTI().getFeatureBits()[Mips::FeatureMips1];
478 }
479 bool hasMips2() const {
480 return getSTI().getFeatureBits()[Mips::FeatureMips2];
481 }
482 bool hasMips3() const {
483 return getSTI().getFeatureBits()[Mips::FeatureMips3];
484 }
485 bool hasMips4() const {
486 return getSTI().getFeatureBits()[Mips::FeatureMips4];
487 }
488 bool hasMips5() const {
489 return getSTI().getFeatureBits()[Mips::FeatureMips5];
490 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000491 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000492 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000493 }
494 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000495 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000496 }
497 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000498 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000499 }
500 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000501 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000502 }
Daniel Sanders17793142015-02-18 16:24:50 +0000503 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000504 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000505 }
506 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000507 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000508 }
509 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000510 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000511 }
512 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000513 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000514 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000515 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000516 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000517 }
518 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000519 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000520 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000521
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000522 bool hasDSP() const {
523 return getSTI().getFeatureBits()[Mips::FeatureDSP];
524 }
525 bool hasDSPR2() const {
526 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
527 }
528 bool hasDSPR3() const {
529 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
530 }
531 bool hasMSA() const {
532 return getSTI().getFeatureBits()[Mips::FeatureMSA];
533 }
Kai Nackee0245392015-01-27 19:11:28 +0000534 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000535 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000536 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000537
Daniel Sandersa6994442015-08-18 12:33:54 +0000538 bool inPicMode() {
539 return IsPicEnabled;
540 }
541
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000542 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000543 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000544 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000545
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000546 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000547 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000548 }
549
Eric Christophere8ae3e32015-05-07 23:10:21 +0000550 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000551 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000552 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000553
Toma Tabacud9d344b2015-04-27 14:05:04 +0000554 /// Warn if RegIndex is the same as the current AT.
555 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000556
557 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000558
559 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000560
561 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
562 AsmToken::TokenKind OperatorToken,
563 MCContext &Ctx) override {
564 switch(OperatorToken) {
565 default:
566 llvm_unreachable("Unknown token");
567 return nullptr;
568 case AsmToken::PercentCall16:
569 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
570 case AsmToken::PercentCall_Hi:
571 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
572 case AsmToken::PercentCall_Lo:
573 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
574 case AsmToken::PercentDtprel_Hi:
575 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
576 case AsmToken::PercentDtprel_Lo:
577 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
578 case AsmToken::PercentGot:
579 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
580 case AsmToken::PercentGot_Disp:
581 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
582 case AsmToken::PercentGot_Hi:
583 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
584 case AsmToken::PercentGot_Lo:
585 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
586 case AsmToken::PercentGot_Ofst:
587 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
588 case AsmToken::PercentGot_Page:
589 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
590 case AsmToken::PercentGottprel:
591 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
592 case AsmToken::PercentGp_Rel:
593 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
594 case AsmToken::PercentHi:
595 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
596 case AsmToken::PercentHigher:
597 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
598 case AsmToken::PercentHighest:
599 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
600 case AsmToken::PercentLo:
601 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
602 case AsmToken::PercentNeg:
603 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
604 case AsmToken::PercentPcrel_Hi:
605 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
606 case AsmToken::PercentPcrel_Lo:
607 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
608 case AsmToken::PercentTlsgd:
609 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
610 case AsmToken::PercentTlsldm:
611 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
612 case AsmToken::PercentTprel_Hi:
613 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
614 case AsmToken::PercentTprel_Lo:
615 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
616 }
617 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000618};
619}
620
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000621namespace {
622
623/// MipsOperand - Instances of this class represent a parsed Mips machine
624/// instruction.
625class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000626public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000627 /// Broad categories of register classes
628 /// The exact class is finalized by the render method.
629 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000630 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000631 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000632 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000633 RegKind_FCC = 4, /// FCC
634 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
635 RegKind_MSACtrl = 16, /// MSA control registers
636 RegKind_COP2 = 32, /// COP2
637 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
638 /// context).
639 RegKind_CCR = 128, /// CCR
640 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000641 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000642 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000643 /// Potentially any (e.g. $1)
644 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
645 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000646 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000647 };
648
649private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000650 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000651 k_Immediate, /// An immediate (possibly involving symbol references)
652 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000653 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000654 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000655 k_RegList, /// A physical register list
656 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000657 } Kind;
658
David Blaikie960ea3f2014-06-08 16:18:35 +0000659public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000660 MipsOperand(KindTy K, MipsAsmParser &Parser)
661 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
662
David Blaikie960ea3f2014-06-08 16:18:35 +0000663private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000664 /// For diagnostics, and checking the assembler temporary
665 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000666
Eric Christopher8996c5d2013-03-15 00:42:55 +0000667 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000668 const char *Data;
669 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000670 };
671
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000672 struct RegIdxOp {
673 unsigned Index; /// Index into the register class
674 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000675 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000676 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000677 };
678
679 struct ImmOp {
680 const MCExpr *Val;
681 };
682
683 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000684 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000685 const MCExpr *Off;
686 };
687
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000688 struct RegListOp {
689 SmallVector<unsigned, 10> *List;
690 };
691
Jack Carterb4dbc172012-09-05 23:34:03 +0000692 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000693 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000694 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000695 struct ImmOp Imm;
696 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000697 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000698 };
699
700 SMLoc StartLoc, EndLoc;
701
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000702 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000703 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
704 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000705 const MCRegisterInfo *RegInfo,
706 SMLoc S, SMLoc E,
707 MipsAsmParser &Parser) {
708 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000709 Op->RegIdx.Index = Index;
710 Op->RegIdx.RegInfo = RegInfo;
711 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000712 Op->RegIdx.Tok.Data = Str.data();
713 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000714 Op->StartLoc = S;
715 Op->EndLoc = E;
716 return Op;
717 }
718
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000719public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000720 /// Coerce the register to GPR32 and return the real register for the current
721 /// target.
722 unsigned getGPR32Reg() const {
723 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000724 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000725 unsigned ClassID = Mips::GPR32RegClassID;
726 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000727 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000728
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000729 /// Coerce the register to GPR32 and return the real register for the current
730 /// target.
731 unsigned getGPRMM16Reg() const {
732 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
733 unsigned ClassID = Mips::GPR32RegClassID;
734 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
735 }
736
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000737 /// Coerce the register to GPR64 and return the real register for the current
738 /// target.
739 unsigned getGPR64Reg() const {
740 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
741 unsigned ClassID = Mips::GPR64RegClassID;
742 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000743 }
744
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000745private:
746 /// Coerce the register to AFGR64 and return the real register for the current
747 /// target.
748 unsigned getAFGR64Reg() const {
749 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
750 if (RegIdx.Index % 2 != 0)
751 AsmParser.Warning(StartLoc, "Float register should be even.");
752 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
753 .getRegister(RegIdx.Index / 2);
754 }
755
756 /// Coerce the register to FGR64 and return the real register for the current
757 /// target.
758 unsigned getFGR64Reg() const {
759 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
760 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
761 .getRegister(RegIdx.Index);
762 }
763
764 /// Coerce the register to FGR32 and return the real register for the current
765 /// target.
766 unsigned getFGR32Reg() const {
767 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
768 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
769 .getRegister(RegIdx.Index);
770 }
771
772 /// Coerce the register to FGRH32 and return the real register for the current
773 /// target.
774 unsigned getFGRH32Reg() const {
775 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
776 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
777 .getRegister(RegIdx.Index);
778 }
779
780 /// Coerce the register to FCC and return the real register for the current
781 /// target.
782 unsigned getFCCReg() const {
783 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
784 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
785 .getRegister(RegIdx.Index);
786 }
787
788 /// Coerce the register to MSA128 and return the real register for the current
789 /// target.
790 unsigned getMSA128Reg() const {
791 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
792 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
793 // identical
794 unsigned ClassID = Mips::MSA128BRegClassID;
795 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
796 }
797
798 /// Coerce the register to MSACtrl and return the real register for the
799 /// current target.
800 unsigned getMSACtrlReg() const {
801 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
802 unsigned ClassID = Mips::MSACtrlRegClassID;
803 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
804 }
805
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000806 /// Coerce the register to COP0 and return the real register for the
807 /// current target.
808 unsigned getCOP0Reg() const {
809 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
810 unsigned ClassID = Mips::COP0RegClassID;
811 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
812 }
813
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000814 /// Coerce the register to COP2 and return the real register for the
815 /// current target.
816 unsigned getCOP2Reg() const {
817 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
818 unsigned ClassID = Mips::COP2RegClassID;
819 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
820 }
821
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000822 /// Coerce the register to COP3 and return the real register for the
823 /// current target.
824 unsigned getCOP3Reg() const {
825 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
826 unsigned ClassID = Mips::COP3RegClassID;
827 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
828 }
829
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 /// Coerce the register to ACC64DSP and return the real register for the
831 /// current target.
832 unsigned getACC64DSPReg() const {
833 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
834 unsigned ClassID = Mips::ACC64DSPRegClassID;
835 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
836 }
837
838 /// Coerce the register to HI32DSP and return the real register for the
839 /// current target.
840 unsigned getHI32DSPReg() const {
841 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
842 unsigned ClassID = Mips::HI32DSPRegClassID;
843 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
844 }
845
846 /// Coerce the register to LO32DSP and return the real register for the
847 /// current target.
848 unsigned getLO32DSPReg() const {
849 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
850 unsigned ClassID = Mips::LO32DSPRegClassID;
851 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
852 }
853
854 /// Coerce the register to CCR and return the real register for the
855 /// current target.
856 unsigned getCCRReg() const {
857 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
858 unsigned ClassID = Mips::CCRRegClassID;
859 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
860 }
861
862 /// Coerce the register to HWRegs and return the real register for the
863 /// current target.
864 unsigned getHWRegsReg() const {
865 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
866 unsigned ClassID = Mips::HWRegsRegClassID;
867 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
868 }
869
870public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000871 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000872 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000873 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000874 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000875 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000876 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000877 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000878 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000879 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000880
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000881 void addRegOperands(MCInst &Inst, unsigned N) const {
882 llvm_unreachable("Use a custom parser instead");
883 }
884
Daniel Sanders21bce302014-04-01 12:35:23 +0000885 /// Render the operand to an MCInst as a GPR32
886 /// Asserts if the wrong number of operands are requested, or the operand
887 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000888 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
889 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000890 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000891 }
892
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000893 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
894 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000895 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000896 }
897
Jozef Kolek1904fa22014-11-24 14:25:53 +0000898 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
899 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000900 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000901 }
902
Zoran Jovanovic41688672015-02-10 16:36:20 +0000903 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
904 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000905 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000906 }
907
Daniel Sanders21bce302014-04-01 12:35:23 +0000908 /// Render the operand to an MCInst as a GPR64
909 /// Asserts if the wrong number of operands are requested, or the operand
910 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000911 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
912 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000913 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000914 }
915
916 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
917 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000918 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000919 }
920
921 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
922 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000923 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000924 }
925
926 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
927 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000928 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000929 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +0000930 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000931 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +0000932 AsmParser.getParser().printError(
933 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
934 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000935 }
936
937 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
938 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000939 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000940 }
941
942 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
943 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000944 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000945 }
946
947 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
948 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000949 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000950 }
951
952 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
953 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000954 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000955 }
956
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000957 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
958 assert(N == 1 && "Invalid number of operands!");
959 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
960 }
961
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000962 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
963 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000964 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000965 }
966
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000967 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
968 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000969 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000970 }
971
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000972 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
973 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000974 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000975 }
976
977 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
978 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000979 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000980 }
981
982 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
983 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000984 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000985 }
986
987 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
988 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000989 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000990 }
991
992 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
993 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000994 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000995 }
996
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000997 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000998 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
999 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001000 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001001 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001002 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001003 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001004 Inst.addOperand(MCOperand::createImm(Imm));
1005 }
1006
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001007 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001008 void addSImmOperands(MCInst &Inst, unsigned N) const {
1009 if (isImm() && !isConstantImm()) {
1010 addExpr(Inst, getImm());
1011 return;
1012 }
1013 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1014 }
1015
1016 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001017 void addUImmOperands(MCInst &Inst, unsigned N) const {
1018 if (isImm() && !isConstantImm()) {
1019 addExpr(Inst, getImm());
1020 return;
1021 }
1022 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1023 }
1024
Daniel Sanders78e89022016-03-11 11:37:50 +00001025 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1026 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1027 assert(N == 1 && "Invalid number of operands!");
1028 int64_t Imm = getConstantImm() - Offset;
1029 Imm = SignExtend64<Bits>(Imm);
1030 Imm += Offset;
1031 Imm += AdjustOffset;
1032 Inst.addOperand(MCOperand::createImm(Imm));
1033 }
1034
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001035 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001036 assert(N == 1 && "Invalid number of operands!");
1037 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001038 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001039 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001040
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001041 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001042 assert(N == 2 && "Invalid number of operands!");
1043
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001044 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1045 ? getMemBase()->getGPR64Reg()
1046 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001047
1048 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001049 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001050 }
1051
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001052 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1053 assert(N == 2 && "Invalid number of operands!");
1054
Jim Grosbache9119e42015-05-13 18:37:00 +00001055 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001056
1057 const MCExpr *Expr = getMemOff();
1058 addExpr(Inst, Expr);
1059 }
1060
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001061 void addRegListOperands(MCInst &Inst, unsigned N) const {
1062 assert(N == 1 && "Invalid number of operands!");
1063
1064 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001065 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001066 }
1067
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001068 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1069 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001070 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001071 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001072 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1073 Inst.addOperand(MCOperand::createReg(
1074 RegIdx.RegInfo->getRegClass(
1075 AsmParser.getABI().AreGprs64bit()
1076 ? Mips::GPR64RegClassID
1077 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1078 Inst.addOperand(MCOperand::createReg(
1079 RegIdx.RegInfo->getRegClass(
1080 AsmParser.getABI().AreGprs64bit()
1081 ? Mips::GPR64RegClassID
1082 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001083 }
1084
Zoran Jovanovic41688672015-02-10 16:36:20 +00001085 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1086 assert(N == 2 && "Invalid number of operands!");
1087 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001088 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001089 }
1090
Craig Topper56c590a2014-04-29 07:58:02 +00001091 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001092 // As a special case until we sort out the definition of div/divu, accept
1093 // $0/$zero here so that MCK_ZERO works correctly.
1094 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001095 }
1096 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001097 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001098 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001099 int64_t Res;
1100 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001101 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001102 bool isConstantImmz() const {
1103 return isConstantImm() && getConstantImm() == 0;
1104 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001105 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1106 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1107 }
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001108 template <unsigned Bits> bool isSImm() const {
1109 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1110 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001111 template <unsigned Bits> bool isUImm() const {
1112 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1113 }
1114 template <unsigned Bits> bool isAnyImm() const {
1115 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1116 isUInt<Bits>(getConstantImm()))
1117 : isImm();
1118 }
Daniel Sanders78e89022016-03-11 11:37:50 +00001119 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1120 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001121 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001122 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1123 return isConstantImm() && getConstantImm() >= Bottom &&
1124 getConstantImm() <= Top;
1125 }
Craig Topper56c590a2014-04-29 07:58:02 +00001126 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001127 // Note: It's not possible to pretend that other operand kinds are tokens.
1128 // The matcher emitter checks tokens first.
1129 return Kind == k_Token;
1130 }
Craig Topper56c590a2014-04-29 07:58:02 +00001131 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001132 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001133 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001134 }
Simon Dardis4ccda502016-05-27 13:56:36 +00001135 // Allow relocation operators.
1136 // FIXME: This predicate and others need to look through binary expressions
1137 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001138 template <unsigned Bits, unsigned ShiftAmount = 0>
1139 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001140 if (!isMem())
1141 return false;
1142 if (!getMemBase()->isGPRAsmReg())
1143 return false;
1144 if (isa<MCTargetExpr>(getMemOff()) ||
1145 (isConstantMemOff() &&
1146 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1147 return true;
1148 MCValue Res;
1149 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1150 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001151 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001152 bool isMemWithGRPMM16Base() const {
1153 return isMem() && getMemBase()->isMM16AsmReg();
1154 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001155 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1156 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1157 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1158 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001159 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1160 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1161 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1162 && (getMemBase()->getGPR32Reg() == Mips::SP);
1163 }
Daniel Sanderse473dc92016-05-09 13:38:25 +00001164 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1165 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1166 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1167 && (getMemBase()->getGPR32Reg() == Mips::GP);
1168 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001169 template <unsigned Bits, unsigned ShiftLeftAmount>
1170 bool isScaledUImm() const {
1171 return isConstantImm() &&
1172 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001173 }
Daniel Sanders97297772016-03-22 14:40:00 +00001174 template <unsigned Bits, unsigned ShiftLeftAmount>
1175 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001176 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1177 return true;
1178 // Operand can also be a symbol or symbol plus offset in case of relocations.
1179 if (Kind != k_Immediate)
1180 return false;
1181 MCValue Res;
1182 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1183 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001184 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001185 bool isRegList16() const {
1186 if (!isRegList())
1187 return false;
1188
1189 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001190 if (Size < 2 || Size > 5)
1191 return false;
1192
1193 unsigned R0 = RegList.List->front();
1194 unsigned R1 = RegList.List->back();
1195 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1196 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001197 return false;
1198
1199 int PrevReg = *RegList.List->begin();
1200 for (int i = 1; i < Size - 1; i++) {
1201 int Reg = (*(RegList.List))[i];
1202 if ( Reg != PrevReg + 1)
1203 return false;
1204 PrevReg = Reg;
1205 }
1206
1207 return true;
1208 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001209 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001210 bool isLSAImm() const {
1211 if (!isConstantImm())
1212 return false;
1213 int64_t Val = getConstantImm();
1214 return 1 <= Val && Val <= 4;
1215 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001216 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001217 bool isMovePRegPair() const {
1218 if (Kind != k_RegList || RegList.List->size() != 2)
1219 return false;
1220
1221 unsigned R0 = RegList.List->front();
1222 unsigned R1 = RegList.List->back();
1223
1224 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1225 (R0 == Mips::A1 && R1 == Mips::A3) ||
1226 (R0 == Mips::A2 && R1 == Mips::A3) ||
1227 (R0 == Mips::A0 && R1 == Mips::S5) ||
1228 (R0 == Mips::A0 && R1 == Mips::S6) ||
1229 (R0 == Mips::A0 && R1 == Mips::A1) ||
1230 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001231 (R0 == Mips::A0 && R1 == Mips::A3) ||
1232 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1233 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1234 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1235 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1236 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1237 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1238 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1239 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001240 return true;
1241
1242 return false;
1243 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001244
1245 StringRef getToken() const {
1246 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001247 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001248 }
Zlatko Buljanba553a62016-05-09 08:07:28 +00001249 bool isRegPair() const {
1250 return Kind == k_RegPair && RegIdx.Index <= 30;
1251 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001252
Craig Topper56c590a2014-04-29 07:58:02 +00001253 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001254 // As a special case until we sort out the definition of div/divu, accept
1255 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001256 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1257 RegIdx.Kind & RegKind_GPR)
1258 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001259
Daniel Sanders976d9382016-07-05 13:38:40 +00001260 llvm_unreachable("Invalid access!");
1261 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001262 }
1263
Jack Carterb4dbc172012-09-05 23:34:03 +00001264 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001265 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001266 return Imm.Val;
1267 }
1268
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001269 int64_t getConstantImm() const {
1270 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001271 int64_t Value = 0;
1272 (void)Val->evaluateAsAbsolute(Value);
1273 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001274 }
1275
1276 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001277 assert((Kind == k_Memory) && "Invalid access!");
1278 return Mem.Base;
1279 }
1280
1281 const MCExpr *getMemOff() const {
1282 assert((Kind == k_Memory) && "Invalid access!");
1283 return Mem.Off;
1284 }
1285
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001286 int64_t getConstantMemOff() const {
1287 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1288 }
1289
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001290 const SmallVectorImpl<unsigned> &getRegList() const {
1291 assert((Kind == k_RegList) && "Invalid access!");
1292 return *(RegList.List);
1293 }
1294
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001295 unsigned getRegPair() const {
1296 assert((Kind == k_RegPair) && "Invalid access!");
1297 return RegIdx.Index;
1298 }
1299
David Blaikie960ea3f2014-06-08 16:18:35 +00001300 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1301 MipsAsmParser &Parser) {
1302 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001303 Op->Tok.Data = Str.data();
1304 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001305 Op->StartLoc = S;
1306 Op->EndLoc = S;
1307 return Op;
1308 }
1309
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001310 /// Create a numeric register (e.g. $1). The exact register remains
1311 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001312 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001313 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1314 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001315 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001316 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001317 }
1318
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001319 /// Create a register that is definitely a GPR.
1320 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001321 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001322 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1323 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1324 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001325 }
1326
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001327 /// Create a register that is definitely a FGR.
1328 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001329 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001330 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1331 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1332 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001333 }
1334
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001335 /// Create a register that is definitely a HWReg.
1336 /// This is typically only used for named registers such as $hwr_cpunum.
1337 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001338 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001339 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001340 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001341 }
1342
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001343 /// Create a register that is definitely an FCC.
1344 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001345 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001346 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1347 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1348 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001349 }
1350
1351 /// Create a register that is definitely an ACC.
1352 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001353 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001354 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1355 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1356 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001357 }
1358
1359 /// Create a register that is definitely an MSA128.
1360 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001361 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001362 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1363 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1364 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001365 }
1366
1367 /// Create a register that is definitely an MSACtrl.
1368 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001369 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001370 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1371 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1372 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001373 }
1374
David Blaikie960ea3f2014-06-08 16:18:35 +00001375 static std::unique_ptr<MipsOperand>
1376 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1377 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001378 Op->Imm.Val = Val;
1379 Op->StartLoc = S;
1380 Op->EndLoc = E;
1381 return Op;
1382 }
1383
David Blaikie960ea3f2014-06-08 16:18:35 +00001384 static std::unique_ptr<MipsOperand>
1385 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1386 SMLoc E, MipsAsmParser &Parser) {
1387 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1388 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001389 Op->Mem.Off = Off;
1390 Op->StartLoc = S;
1391 Op->EndLoc = E;
1392 return Op;
1393 }
1394
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001395 static std::unique_ptr<MipsOperand>
1396 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1397 MipsAsmParser &Parser) {
1398 assert (Regs.size() > 0 && "Empty list not allowed");
1399
1400 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001401 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001402 Op->StartLoc = StartLoc;
1403 Op->EndLoc = EndLoc;
1404 return Op;
1405 }
1406
Daniel Sandersd044e492016-05-09 13:10:57 +00001407 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1408 SMLoc S, SMLoc E,
1409 MipsAsmParser &Parser) {
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001410 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001411 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001412 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1413 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001414 Op->StartLoc = S;
1415 Op->EndLoc = E;
1416 return Op;
1417 }
1418
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001419 bool isGPRAsmReg() const {
1420 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001421 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001422 bool isMM16AsmReg() const {
1423 if (!(isRegIdx() && RegIdx.Kind))
1424 return false;
1425 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1426 || RegIdx.Index == 16 || RegIdx.Index == 17);
1427 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001428 bool isMM16AsmRegZero() const {
1429 if (!(isRegIdx() && RegIdx.Kind))
1430 return false;
1431 return (RegIdx.Index == 0 ||
1432 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1433 RegIdx.Index == 17);
1434 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001435 bool isMM16AsmRegMoveP() const {
1436 if (!(isRegIdx() && RegIdx.Kind))
1437 return false;
1438 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1439 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1440 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001441 bool isFGRAsmReg() const {
1442 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1443 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001444 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001445 bool isHWRegsAsmReg() const {
1446 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001447 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001448 bool isCCRAsmReg() const {
1449 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001450 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001451 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001452 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1453 return false;
1454 if (!AsmParser.hasEightFccRegisters())
1455 return RegIdx.Index == 0;
1456 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001457 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001458 bool isACCAsmReg() const {
1459 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001460 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001461 bool isCOP0AsmReg() const {
1462 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1463 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001464 bool isCOP2AsmReg() const {
1465 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001466 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001467 bool isCOP3AsmReg() const {
1468 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1469 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001470 bool isMSA128AsmReg() const {
1471 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001472 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001473 bool isMSACtrlAsmReg() const {
1474 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001475 }
1476
Jack Carterb4dbc172012-09-05 23:34:03 +00001477 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001478 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001479 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001480 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001481
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001482 virtual ~MipsOperand() {
1483 switch (Kind) {
1484 case k_Immediate:
1485 break;
1486 case k_Memory:
1487 delete Mem.Base;
1488 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001489 case k_RegList:
1490 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001491 case k_RegisterIndex:
1492 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001493 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001494 break;
1495 }
1496 }
1497
Craig Topper56c590a2014-04-29 07:58:02 +00001498 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001499 switch (Kind) {
1500 case k_Immediate:
1501 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001502 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001503 OS << ">";
1504 break;
1505 case k_Memory:
1506 OS << "Mem<";
1507 Mem.Base->print(OS);
1508 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001509 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001510 OS << ">";
1511 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001512 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001513 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1514 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001515 break;
1516 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001517 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001518 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001519 case k_RegList:
1520 OS << "RegList< ";
1521 for (auto Reg : (*RegList.List))
1522 OS << Reg << " ";
1523 OS << ">";
1524 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001525 case k_RegPair:
1526 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1527 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001528 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001529 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001530
1531 bool isValidForTie(const MipsOperand &Other) const {
1532 if (Kind != Other.Kind)
1533 return false;
1534
1535 switch (Kind) {
1536 default:
1537 llvm_unreachable("Unexpected kind");
1538 return false;
1539 case k_RegisterIndex: {
1540 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1541 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1542 return Token == OtherToken;
1543 }
1544 }
1545 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001546}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001547} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001548
Jack Carter9e65aa32013-03-22 00:05:30 +00001549namespace llvm {
1550extern const MCInstrDesc MipsInsts[];
1551}
1552static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1553 return MipsInsts[Opcode];
1554}
1555
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001556static bool hasShortDelaySlot(unsigned Opcode) {
1557 switch (Opcode) {
1558 case Mips::JALS_MM:
1559 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001560 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001561 case Mips::BGEZALS_MM:
1562 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001563 return true;
1564 default:
1565 return false;
1566 }
1567}
1568
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001569static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1570 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1571 return &SRExpr->getSymbol();
1572 }
1573
1574 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1575 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1576 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1577
1578 if (LHSSym)
1579 return LHSSym;
1580
1581 if (RHSSym)
1582 return RHSSym;
1583
1584 return nullptr;
1585 }
1586
1587 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1588 return getSingleMCSymbol(UExpr->getSubExpr());
1589
1590 return nullptr;
1591}
1592
1593static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1594 if (isa<MCSymbolRefExpr>(Expr))
1595 return 1;
1596
1597 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1598 return countMCSymbolRefExpr(BExpr->getLHS()) +
1599 countMCSymbolRefExpr(BExpr->getRHS());
1600
1601 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1602 return countMCSymbolRefExpr(UExpr->getSubExpr());
1603
1604 return 0;
1605}
1606
Jack Carter9e65aa32013-03-22 00:05:30 +00001607bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001608 MCStreamer &Out,
1609 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001610 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001611 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001612 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001613
Jack Carter9e65aa32013-03-22 00:05:30 +00001614 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001615
1616 if (MCID.isBranch() || MCID.isCall()) {
1617 const unsigned Opcode = Inst.getOpcode();
1618 MCOperand Offset;
1619
1620 switch (Opcode) {
1621 default:
1622 break;
Kai Nackee0245392015-01-27 19:11:28 +00001623 case Mips::BBIT0:
1624 case Mips::BBIT032:
1625 case Mips::BBIT1:
1626 case Mips::BBIT132:
1627 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001628 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001629
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001630 case Mips::BEQ:
1631 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001632 case Mips::BEQ_MM:
1633 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001634 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001635 Offset = Inst.getOperand(2);
1636 if (!Offset.isImm())
1637 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001638 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001639 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001640 if (OffsetToAlignment(Offset.getImm(),
1641 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001642 return Error(IDLoc, "branch to misaligned address");
1643 break;
1644 case Mips::BGEZ:
1645 case Mips::BGTZ:
1646 case Mips::BLEZ:
1647 case Mips::BLTZ:
1648 case Mips::BGEZAL:
1649 case Mips::BLTZAL:
1650 case Mips::BC1F:
1651 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001652 case Mips::BGEZ_MM:
1653 case Mips::BGTZ_MM:
1654 case Mips::BLEZ_MM:
1655 case Mips::BLTZ_MM:
1656 case Mips::BGEZAL_MM:
1657 case Mips::BLTZAL_MM:
1658 case Mips::BC1F_MM:
1659 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001660 case Mips::BC1EQZC_MMR6:
1661 case Mips::BC1NEZC_MMR6:
1662 case Mips::BC2EQZC_MMR6:
1663 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001664 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001665 Offset = Inst.getOperand(1);
1666 if (!Offset.isImm())
1667 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001668 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001669 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001670 if (OffsetToAlignment(Offset.getImm(),
1671 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001672 return Error(IDLoc, "branch to misaligned address");
1673 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001674 case Mips::BGEC: case Mips::BGEC_MMR6:
1675 case Mips::BLTC: case Mips::BLTC_MMR6:
1676 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1677 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1678 case Mips::BEQC: case Mips::BEQC_MMR6:
1679 case Mips::BNEC: case Mips::BNEC_MMR6:
1680 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1681 Offset = Inst.getOperand(2);
1682 if (!Offset.isImm())
1683 break; // We'll deal with this situation later on when applying fixups.
1684 if (!isIntN(18, Offset.getImm()))
1685 return Error(IDLoc, "branch target out of range");
1686 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1687 return Error(IDLoc, "branch to misaligned address");
1688 break;
1689 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1690 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1691 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1692 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1693 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1694 Offset = Inst.getOperand(1);
1695 if (!Offset.isImm())
1696 break; // We'll deal with this situation later on when applying fixups.
1697 if (!isIntN(18, Offset.getImm()))
1698 return Error(IDLoc, "branch target out of range");
1699 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1700 return Error(IDLoc, "branch to misaligned address");
1701 break;
1702 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1703 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1704 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1705 Offset = Inst.getOperand(1);
1706 if (!Offset.isImm())
1707 break; // We'll deal with this situation later on when applying fixups.
1708 if (!isIntN(23, Offset.getImm()))
1709 return Error(IDLoc, "branch target out of range");
1710 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1711 return Error(IDLoc, "branch to misaligned address");
1712 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001713 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001714 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001715 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001716 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001717 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1718 Offset = Inst.getOperand(1);
1719 if (!Offset.isImm())
1720 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001721 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001722 return Error(IDLoc, "branch target out of range");
1723 if (OffsetToAlignment(Offset.getImm(), 2LL))
1724 return Error(IDLoc, "branch to misaligned address");
1725 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001726 }
1727 }
1728
Daniel Sandersa84989a2014-06-16 13:25:35 +00001729 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1730 // We still accept it but it is a normal nop.
1731 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1732 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1733 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1734 "nop instruction");
1735 }
1736
Kai Nackee0245392015-01-27 19:11:28 +00001737 if (hasCnMips()) {
1738 const unsigned Opcode = Inst.getOpcode();
1739 MCOperand Opnd;
1740 int Imm;
1741
1742 switch (Opcode) {
1743 default:
1744 break;
1745
1746 case Mips::BBIT0:
1747 case Mips::BBIT032:
1748 case Mips::BBIT1:
1749 case Mips::BBIT132:
1750 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1751 // The offset is handled above
1752 Opnd = Inst.getOperand(1);
1753 if (!Opnd.isImm())
1754 return Error(IDLoc, "expected immediate operand kind");
1755 Imm = Opnd.getImm();
1756 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1757 Opcode == Mips::BBIT1 ? 63 : 31))
1758 return Error(IDLoc, "immediate operand value out of range");
1759 if (Imm > 31) {
1760 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1761 : Mips::BBIT132);
1762 Inst.getOperand(1).setImm(Imm - 32);
1763 }
1764 break;
1765
Kai Nackee0245392015-01-27 19:11:28 +00001766 case Mips::SEQi:
1767 case Mips::SNEi:
1768 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1769 Opnd = Inst.getOperand(2);
1770 if (!Opnd.isImm())
1771 return Error(IDLoc, "expected immediate operand kind");
1772 Imm = Opnd.getImm();
1773 if (!isInt<10>(Imm))
1774 return Error(IDLoc, "immediate operand value out of range");
1775 break;
1776 }
1777 }
1778
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001779 // This expansion is not in a function called by tryExpandInstruction()
1780 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001781 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1782 inPicMode()) {
1783 warnIfNoMacro(IDLoc);
1784
1785 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1786
1787 // We can do this expansion if there's only 1 symbol in the argument
1788 // expression.
1789 if (countMCSymbolRefExpr(JalExpr) > 1)
1790 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1791
1792 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001793 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001794 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1795
1796 // FIXME: Add support for label+offset operands (currently causes an error).
1797 // FIXME: Add support for forward-declared local symbols.
1798 // FIXME: Add expansion for when the LargeGOT option is enabled.
1799 if (JalSym->isInSection() || JalSym->isTemporary()) {
1800 if (isABI_O32()) {
1801 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001802 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001803 // R_(MICRO)MIPS_GOT16 label
1804 // addiu $25, $25, 0
1805 // R_(MICRO)MIPS_LO16 label
1806 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001807 const MCExpr *Got16RelocExpr =
1808 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1809 const MCExpr *Lo16RelocExpr =
1810 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001811
Daniel Sandersa736b372016-04-29 13:33:12 +00001812 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1813 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1814 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1815 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001816 } else if (isABI_N32() || isABI_N64()) {
1817 // If it's a local symbol and the N32/N64 ABIs are being used,
1818 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001819 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001820 // R_(MICRO)MIPS_GOT_DISP label
1821 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001822 const MCExpr *GotDispRelocExpr =
1823 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001824
Daniel Sandersa736b372016-04-29 13:33:12 +00001825 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1826 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1827 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001828 }
1829 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001830 // If it's an external/weak symbol, we expand to:
1831 // lw/ld $25, 0($gp)
1832 // R_(MICRO)MIPS_CALL16 label
1833 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001834 const MCExpr *Call16RelocExpr =
1835 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001836
Daniel Sandersa736b372016-04-29 13:33:12 +00001837 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1838 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001839 }
1840
1841 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001842 if (IsCpRestoreSet && inMicroMipsMode())
1843 JalrInst.setOpcode(Mips::JALRS_MM);
1844 else
1845 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001846 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1847 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1848
1849 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1850 // This relocation is supposed to be an optimization hint for the linker
1851 // and is not necessary for correctness.
1852
1853 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001854 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001855 }
1856
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001857 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
1858 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001859 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001860 // reference or immediate we may have to expand instructions.
1861 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001862 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001863 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1864 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001865 MCOperand &Op = Inst.getOperand(i);
1866 if (Op.isImm()) {
1867 int MemOffset = Op.getImm();
1868 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001869 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001870 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00001871 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001872 }
1873 } else if (Op.isExpr()) {
1874 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001875 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001876 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001877 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001878 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001879 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001880 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00001881 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001882 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001883 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001884 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00001885 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001886 }
1887 }
1888 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001889 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001890 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001891
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001892 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001893 if (MCID.mayLoad()) {
1894 // Try to create 16-bit GP relative load instruction.
1895 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1896 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1897 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1898 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1899 MCOperand &Op = Inst.getOperand(i);
1900 if (Op.isImm()) {
1901 int MemOffset = Op.getImm();
1902 MCOperand &DstReg = Inst.getOperand(0);
1903 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001904 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001905 getContext().getRegisterInfo()->getRegClass(
1906 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001907 (BaseReg.getReg() == Mips::GP ||
1908 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001909
Daniel Sandersa736b372016-04-29 13:33:12 +00001910 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1911 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001912 return false;
1913 }
1914 }
1915 }
1916 } // for
1917 } // if load
1918
1919 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1920
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001921 MCOperand Opnd;
1922 int Imm;
1923
1924 switch (Inst.getOpcode()) {
1925 default:
1926 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001927 case Mips::ADDIUSP_MM:
1928 Opnd = Inst.getOperand(0);
1929 if (!Opnd.isImm())
1930 return Error(IDLoc, "expected immediate operand kind");
1931 Imm = Opnd.getImm();
1932 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1933 Imm % 4 != 0)
1934 return Error(IDLoc, "immediate operand value out of range");
1935 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001936 case Mips::SLL16_MM:
1937 case Mips::SRL16_MM:
1938 Opnd = Inst.getOperand(2);
1939 if (!Opnd.isImm())
1940 return Error(IDLoc, "expected immediate operand kind");
1941 Imm = Opnd.getImm();
1942 if (Imm < 1 || Imm > 8)
1943 return Error(IDLoc, "immediate operand value out of range");
1944 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001945 case Mips::LI16_MM:
1946 Opnd = Inst.getOperand(1);
1947 if (!Opnd.isImm())
1948 return Error(IDLoc, "expected immediate operand kind");
1949 Imm = Opnd.getImm();
1950 if (Imm < -1 || Imm > 126)
1951 return Error(IDLoc, "immediate operand value out of range");
1952 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001953 case Mips::ADDIUR2_MM:
1954 Opnd = Inst.getOperand(2);
1955 if (!Opnd.isImm())
1956 return Error(IDLoc, "expected immediate operand kind");
1957 Imm = Opnd.getImm();
1958 if (!(Imm == 1 || Imm == -1 ||
1959 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1960 return Error(IDLoc, "immediate operand value out of range");
1961 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001962 case Mips::ANDI16_MM:
1963 Opnd = Inst.getOperand(2);
1964 if (!Opnd.isImm())
1965 return Error(IDLoc, "expected immediate operand kind");
1966 Imm = Opnd.getImm();
1967 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1968 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1969 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1970 return Error(IDLoc, "immediate operand value out of range");
1971 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001972 case Mips::LBU16_MM:
1973 Opnd = Inst.getOperand(2);
1974 if (!Opnd.isImm())
1975 return Error(IDLoc, "expected immediate operand kind");
1976 Imm = Opnd.getImm();
1977 if (Imm < -1 || Imm > 14)
1978 return Error(IDLoc, "immediate operand value out of range");
1979 break;
1980 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001981 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001982 Opnd = Inst.getOperand(2);
1983 if (!Opnd.isImm())
1984 return Error(IDLoc, "expected immediate operand kind");
1985 Imm = Opnd.getImm();
1986 if (Imm < 0 || Imm > 15)
1987 return Error(IDLoc, "immediate operand value out of range");
1988 break;
1989 case Mips::LHU16_MM:
1990 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001991 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001992 Opnd = Inst.getOperand(2);
1993 if (!Opnd.isImm())
1994 return Error(IDLoc, "expected immediate operand kind");
1995 Imm = Opnd.getImm();
1996 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1997 return Error(IDLoc, "immediate operand value out of range");
1998 break;
1999 case Mips::LW16_MM:
2000 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002001 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002002 Opnd = Inst.getOperand(2);
2003 if (!Opnd.isImm())
2004 return Error(IDLoc, "expected immediate operand kind");
2005 Imm = Opnd.getImm();
2006 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2007 return Error(IDLoc, "immediate operand value out of range");
2008 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002009 case Mips::ADDIUPC_MM:
2010 MCOperand Opnd = Inst.getOperand(1);
2011 if (!Opnd.isImm())
2012 return Error(IDLoc, "expected immediate operand kind");
2013 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002014 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002015 return Error(IDLoc, "immediate operand value out of range");
2016 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002017 }
2018 }
2019
Daniel Sandersd8c07762016-04-18 12:35:36 +00002020 bool FillDelaySlot =
2021 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2022 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002023 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002024
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002025 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002026 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002027 switch (ExpandResult) {
2028 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002029 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002030 break;
2031 case MER_Success:
2032 break;
2033 case MER_Fail:
2034 return true;
2035 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002036
Daniel Sanderscda908a2016-05-16 09:10:13 +00002037 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2038 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2039 if (inMicroMipsMode())
2040 TOut.setUsesMicroMips();
2041
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002042 // If this instruction has a delay slot and .set reorder is active,
2043 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002044 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002045 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2046 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002047 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002048
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002049 if ((Inst.getOpcode() == Mips::JalOneReg ||
2050 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2051 isPicAndNotNxxAbi()) {
2052 if (IsCpRestoreSet) {
2053 // We need a NOP between the JALR and the LW:
2054 // If .set reorder has been used, we've already emitted a NOP.
2055 // If .set noreorder has been used, we need to emit a NOP at this point.
2056 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002057 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2058 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002059
2060 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002061 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002062 } else
2063 Warning(IDLoc, "no .cprestore used in PIC mode");
2064 }
2065
Jack Carter9e65aa32013-03-22 00:05:30 +00002066 return false;
2067}
2068
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002069MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002070MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2071 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002072 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002073 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002074 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002075 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002076 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002077 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002078 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002079 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002080 case Mips::LoadAddrImm64:
2081 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2082 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2083 "expected immediate operand kind");
2084
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002085 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2086 Inst.getOperand(1),
2087 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002088 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002089 ? MER_Fail
2090 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002091 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002092 case Mips::LoadAddrReg64:
2093 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2094 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2095 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2096 "expected immediate operand kind");
2097
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002098 return expandLoadAddress(Inst.getOperand(0).getReg(),
2099 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2100 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002101 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002102 ? MER_Fail
2103 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002104 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002105 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002106 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2107 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002108 case Mips::SWM_MM:
2109 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002110 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2111 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002112 case Mips::JalOneReg:
2113 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002114 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002115 case Mips::BneImm:
2116 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002117 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002118 case Mips::BLT:
2119 case Mips::BLE:
2120 case Mips::BGE:
2121 case Mips::BGT:
2122 case Mips::BLTU:
2123 case Mips::BLEU:
2124 case Mips::BGEU:
2125 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002126 case Mips::BLTL:
2127 case Mips::BLEL:
2128 case Mips::BGEL:
2129 case Mips::BGTL:
2130 case Mips::BLTUL:
2131 case Mips::BLEUL:
2132 case Mips::BGEUL:
2133 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002134 case Mips::BLTImmMacro:
2135 case Mips::BLEImmMacro:
2136 case Mips::BGEImmMacro:
2137 case Mips::BGTImmMacro:
2138 case Mips::BLTUImmMacro:
2139 case Mips::BLEUImmMacro:
2140 case Mips::BGEUImmMacro:
2141 case Mips::BGTUImmMacro:
2142 case Mips::BLTLImmMacro:
2143 case Mips::BLELImmMacro:
2144 case Mips::BGELImmMacro:
2145 case Mips::BGTLImmMacro:
2146 case Mips::BLTULImmMacro:
2147 case Mips::BLEULImmMacro:
2148 case Mips::BGEULImmMacro:
2149 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002150 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002151 case Mips::SDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002152 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2153 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002154 case Mips::DSDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002155 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2156 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002157 case Mips::UDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002158 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2159 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002160 case Mips::DUDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002161 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2162 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002163 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002164 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2165 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002166 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002167 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002168 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002169 case Mips::PseudoTRUNC_W_D:
2170 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2171 : MER_Success;
2172 case Mips::Ulh:
2173 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2174 case Mips::Ulhu:
2175 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2176 case Mips::Ulw:
2177 return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2178 case Mips::NORImm:
2179 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002180 case Mips::ADDi:
2181 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002182 case Mips::SLTi:
2183 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002184 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2185 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2186 int64_t ImmValue = Inst.getOperand(2).getImm();
2187 if (isInt<16>(ImmValue))
2188 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002189 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2190 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002191 }
2192 return MER_NotAMacro;
2193 case Mips::ANDi:
2194 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002195 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002196 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2197 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2198 int64_t ImmValue = Inst.getOperand(2).getImm();
2199 if (isUInt<16>(ImmValue))
2200 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002201 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2202 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002203 }
2204 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002205 case Mips::ROL:
2206 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002207 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002208 case Mips::ROLImm:
2209 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002210 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002211 case Mips::DROL:
2212 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002213 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002214 case Mips::DROLImm:
2215 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002216 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002217 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002218 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002219 case Mips::LDMacro:
2220 case Mips::SDMacro:
2221 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2222 Inst.getOpcode() == Mips::LDMacro)
2223 ? MER_Fail
2224 : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002225 }
Jack Carter30a59822012-10-04 04:03:53 +00002226}
Jack Carter92995f12012-10-06 00:53:28 +00002227
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002228bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002229 MCStreamer &Out,
2230 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002231 MipsTargetStreamer &TOut = getTargetStreamer();
2232
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002233 // Create a JALR instruction which is going to replace the pseudo-JAL.
2234 MCInst JalrInst;
2235 JalrInst.setLoc(IDLoc);
2236 const MCOperand FirstRegOp = Inst.getOperand(0);
2237 const unsigned Opcode = Inst.getOpcode();
2238
2239 if (Opcode == Mips::JalOneReg) {
2240 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002241 if (IsCpRestoreSet && inMicroMipsMode()) {
2242 JalrInst.setOpcode(Mips::JALRS16_MM);
2243 JalrInst.addOperand(FirstRegOp);
2244 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002245 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002246 JalrInst.addOperand(FirstRegOp);
2247 } else {
2248 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002249 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002250 JalrInst.addOperand(FirstRegOp);
2251 }
2252 } else if (Opcode == Mips::JalTwoReg) {
2253 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002254 if (IsCpRestoreSet && inMicroMipsMode())
2255 JalrInst.setOpcode(Mips::JALRS_MM);
2256 else
2257 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002258 JalrInst.addOperand(FirstRegOp);
2259 const MCOperand SecondRegOp = Inst.getOperand(1);
2260 JalrInst.addOperand(SecondRegOp);
2261 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002262 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002263
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002264 // If .set reorder is active and branch instruction has a delay slot,
2265 // emit a NOP after it.
2266 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002267 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2268 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2269 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002270
2271 return false;
2272}
2273
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002274/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002275template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002276 unsigned BitNum = findFirstSet(x);
2277
2278 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2279}
2280
2281/// Load (or add) an immediate into a register.
2282///
2283/// @param ImmValue The immediate to load.
2284/// @param DstReg The register that will hold the immediate.
2285/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2286/// for a simple initialization.
2287/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2288/// @param IsAddress True if the immediate represents an address. False if it
2289/// is an integer.
2290/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002291bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002292 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002293 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2294 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002295 MipsTargetStreamer &TOut = getTargetStreamer();
2296
Toma Tabacu00e98672015-05-01 12:19:27 +00002297 if (!Is32BitImm && !isGP64bit()) {
2298 Error(IDLoc, "instruction requires a 64-bit architecture");
2299 return true;
2300 }
2301
Daniel Sanders03f9c012015-07-14 12:24:22 +00002302 if (Is32BitImm) {
2303 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2304 // Sign extend up to 64-bit so that the predicates match the hardware
2305 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2306 // true.
2307 ImmValue = SignExtend64<32>(ImmValue);
2308 } else {
2309 Error(IDLoc, "instruction requires a 32-bit immediate");
2310 return true;
2311 }
2312 }
2313
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002314 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2315 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2316
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002317 bool UseSrcReg = false;
2318 if (SrcReg != Mips::NoRegister)
2319 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002320
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002321 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002322 if (UseSrcReg &&
2323 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002324 // At this point we need AT to perform the expansions and we exit if it is
2325 // not available.
2326 unsigned ATReg = getATReg(IDLoc);
2327 if (!ATReg)
2328 return true;
2329 TmpReg = ATReg;
2330 }
2331
Daniel Sanders03f9c012015-07-14 12:24:22 +00002332 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002333 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002334 SrcReg = ZeroReg;
2335
2336 // This doesn't quite follow the usual ABI expectations for N32 but matches
2337 // traditional assembler behaviour. N32 would normally use addiu for both
2338 // integers and addresses.
2339 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002340 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002341 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002342 }
2343
Daniel Sandersa736b372016-04-29 13:33:12 +00002344 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002345 return false;
2346 }
2347
2348 if (isUInt<16>(ImmValue)) {
2349 unsigned TmpReg = DstReg;
2350 if (SrcReg == DstReg) {
2351 TmpReg = getATReg(IDLoc);
2352 if (!TmpReg)
2353 return true;
2354 }
2355
Daniel Sandersa736b372016-04-29 13:33:12 +00002356 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002357 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002358 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002359 return false;
2360 }
2361
2362 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002363 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002364
Toma Tabacu79588102015-04-29 10:19:56 +00002365 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2366 uint16_t Bits15To0 = ImmValue & 0xffff;
2367
Toma Tabacua3d056f2015-05-15 09:42:11 +00002368 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002369 // Traditional behaviour seems to special case this particular value. It's
2370 // not clear why other masks are handled differently.
2371 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002372 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2373 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002374 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002375 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002376 return false;
2377 }
2378
2379 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002380 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002381 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2382 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002383 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002384 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002385 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002386 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002387 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002388 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002389
Daniel Sandersa736b372016-04-29 13:33:12 +00002390 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002391 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002392 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002393 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002394 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002395 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002396 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002397
2398 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2399 if (Is32BitImm) {
2400 Error(IDLoc, "instruction requires a 32-bit immediate");
2401 return true;
2402 }
2403
2404 // Traditionally, these immediates are shifted as little as possible and as
2405 // such we align the most significant bit to bit 15 of our temporary.
2406 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2407 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2408 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2409 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002410 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2411 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002412
2413 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002414 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002415
2416 return false;
2417 }
2418
2419 warnIfNoMacro(IDLoc);
2420
2421 // The remaining case is packed with a sequence of dsll and ori with zeros
2422 // being omitted and any neighbouring dsll's being coalesced.
2423 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2424
2425 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2426 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002427 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002428 return false;
2429
2430 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2431 // skip it and defer the shift to the next chunk.
2432 unsigned ShiftCarriedForwards = 16;
2433 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2434 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2435
2436 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002437 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2438 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002439 ShiftCarriedForwards = 0;
2440 }
2441
2442 ShiftCarriedForwards += 16;
2443 }
2444 ShiftCarriedForwards -= 16;
2445
2446 // Finish any remaining shifts left by trailing zeros.
2447 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002448 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002449
2450 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002451 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002452
Matheus Almeida3813d572014-06-19 14:39:14 +00002453 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002454}
Jack Carter92995f12012-10-06 00:53:28 +00002455
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002456bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002457 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002458 const MCOperand &ImmOp = Inst.getOperand(1);
2459 assert(ImmOp.isImm() && "expected immediate operand kind");
2460 const MCOperand &DstRegOp = Inst.getOperand(0);
2461 assert(DstRegOp.isReg() && "expected register operand kind");
2462
2463 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002464 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002465 return true;
2466
2467 return false;
2468}
2469
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002470bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2471 const MCOperand &Offset,
2472 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002473 MCStreamer &Out,
2474 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002475 // la can't produce a usable address when addresses are 64-bit.
2476 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2477 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2478 // We currently can't do this because we depend on the equality
2479 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2480 Error(IDLoc, "la used to load 64-bit address");
2481 // Continue as if we had 'dla' instead.
2482 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002483 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002484 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002485
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002486 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002487 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002488 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002489 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002490 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002491
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002492 if (!Offset.isImm())
2493 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002494 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002495
Scott Egerton24557012016-01-21 15:11:01 +00002496 if (!ABI.ArePtrs64bit()) {
2497 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2498 Is32BitAddress = true;
2499 }
2500
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002501 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002502 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002503}
2504
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002505bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2506 unsigned DstReg, unsigned SrcReg,
2507 bool Is32BitSym, SMLoc IDLoc,
2508 MCStreamer &Out,
2509 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002510 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002511 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002512 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002513
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002514 if (inPicMode() && ABI.IsO32()) {
2515 MCValue Res;
2516 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2517 Error(IDLoc, "expected relocatable expression");
2518 return true;
2519 }
2520 if (Res.getSymB() != nullptr) {
2521 Error(IDLoc, "expected relocatable expression with only one symbol");
2522 return true;
2523 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002524
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002525 // The case where the result register is $25 is somewhat special. If the
2526 // symbol in the final relocation is external and not modified with a
2527 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2528 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2529 Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
2530 !Res.getSymA()->getSymbol().isTemporary()) {
2531 const MCExpr *CallExpr =
2532 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2533 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2534 MCOperand::createExpr(CallExpr), IDLoc, STI);
2535 return false;
2536 }
2537
2538 // The remaining cases are:
2539 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2540 // >addiu $tmp, $tmp, %lo(offset)
2541 // >addiu $rd, $tmp, $rs
2542 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2543 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2544 // >addiu $rd, $tmp, $rs
2545 // The addiu's marked with a '>' may be omitted if they are redundant. If
2546 // this happens then the last instruction must use $rd as the result
2547 // register.
2548 const MipsMCExpr *GotExpr =
2549 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2550 const MCExpr *LoExpr = nullptr;
2551 if (Res.getSymA()->getSymbol().isInSection() ||
2552 Res.getSymA()->getSymbol().isTemporary())
2553 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2554 else if (Res.getConstant() != 0) {
2555 // External symbols fully resolve the symbol with just the %got(symbol)
2556 // but we must still account for any offset to the symbol for expressions
2557 // like symbol+8.
2558 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2559 }
2560
2561 unsigned TmpReg = DstReg;
2562 if (UseSrcReg &&
2563 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2564 SrcReg)) {
2565 // If $rs is the same as $rd, we need to use AT.
2566 // If it is not available we exit.
2567 unsigned ATReg = getATReg(IDLoc);
2568 if (!ATReg)
2569 return true;
2570 TmpReg = ATReg;
2571 }
2572
2573 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2574 MCOperand::createExpr(GotExpr), IDLoc, STI);
2575
2576 if (LoExpr)
2577 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2578 IDLoc, STI);
2579
2580 if (UseSrcReg)
2581 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2582
2583 return false;
2584 }
2585
2586 const MipsMCExpr *HiExpr =
2587 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2588 const MipsMCExpr *LoExpr =
2589 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002590
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002591 // This is the 64-bit symbol address expansion.
2592 if (ABI.ArePtrs64bit() && isGP64bit()) {
2593 // We always need AT for the 64-bit expansion.
2594 // If it is not available we exit.
2595 unsigned ATReg = getATReg(IDLoc);
2596 if (!ATReg)
2597 return true;
2598
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002599 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002600 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002601 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002602 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002603
Scott Egerton24557012016-01-21 15:11:01 +00002604 if (UseSrcReg &&
2605 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2606 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002607 // If $rs is the same as $rd:
2608 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2609 // daddiu $at, $at, %higher(sym)
2610 // dsll $at, $at, 16
2611 // daddiu $at, $at, %hi(sym)
2612 // dsll $at, $at, 16
2613 // daddiu $at, $at, %lo(sym)
2614 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002615 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2616 STI);
2617 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2618 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2619 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2620 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2621 IDLoc, STI);
2622 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2623 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2624 IDLoc, STI);
2625 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002626
2627 return false;
2628 }
2629
2630 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2631 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2632 // lui $at, %hi(sym)
2633 // daddiu $rd, $rd, %higher(sym)
2634 // daddiu $at, $at, %lo(sym)
2635 // dsll32 $rd, $rd, 0
2636 // daddu $rd, $rd, $at
2637 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002638 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2639 STI);
2640 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2641 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2642 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2643 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2644 IDLoc, STI);
2645 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2646 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002647 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002648 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002649
2650 return false;
2651 }
2652
2653 // And now, the 32-bit symbol address expansion:
2654 // If $rs is the same as $rd:
2655 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2656 // ori $at, $at, %lo(sym)
2657 // addu $rd, $at, $rd
2658 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2659 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2660 // ori $rd, $rd, %lo(sym)
2661 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002662 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002663 if (UseSrcReg &&
2664 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002665 // If $rs is the same as $rd, we need to use AT.
2666 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002667 unsigned ATReg = getATReg(IDLoc);
2668 if (!ATReg)
2669 return true;
2670 TmpReg = ATReg;
2671 }
2672
Daniel Sandersa736b372016-04-29 13:33:12 +00002673 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2674 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2675 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002676
Toma Tabacufb9d1252015-06-22 12:08:39 +00002677 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002678 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002679 else
Scott Egerton24557012016-01-21 15:11:01 +00002680 assert(
2681 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002682
Toma Tabacu674825c2015-06-16 12:16:24 +00002683 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002684}
2685
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002686bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2687 MCStreamer &Out,
2688 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002689 MipsTargetStreamer &TOut = getTargetStreamer();
2690
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002691 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2692 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002693
2694 MCOperand Offset = Inst.getOperand(0);
2695 if (Offset.isExpr()) {
2696 Inst.clear();
2697 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002698 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2699 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2700 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002701 } else {
2702 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002703 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002704 // If offset fits into 11 bits then this instruction becomes microMIPS
2705 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002706 if (inMicroMipsMode())
2707 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002708 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002709 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00002710 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002711 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00002712 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002713 Inst.clear();
2714 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002715 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2716 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2717 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002718 }
2719 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002720 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002721
Zoran Jovanovicada70912015-09-07 11:56:37 +00002722 // If .set reorder is active and branch instruction has a delay slot,
2723 // emit a NOP after it.
2724 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2725 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002726 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002727
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002728 return false;
2729}
2730
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002731bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2732 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002733 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002734 const MCOperand &DstRegOp = Inst.getOperand(0);
2735 assert(DstRegOp.isReg() && "expected register operand kind");
2736
2737 const MCOperand &ImmOp = Inst.getOperand(1);
2738 assert(ImmOp.isImm() && "expected immediate operand kind");
2739
2740 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002741 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2742 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002743
2744 unsigned OpCode = 0;
2745 switch(Inst.getOpcode()) {
2746 case Mips::BneImm:
2747 OpCode = Mips::BNE;
2748 break;
2749 case Mips::BeqImm:
2750 OpCode = Mips::BEQ;
2751 break;
2752 default:
2753 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2754 break;
2755 }
2756
2757 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002758 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002759 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2760 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002761 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002762 warnIfNoMacro(IDLoc);
2763
2764 unsigned ATReg = getATReg(IDLoc);
2765 if (!ATReg)
2766 return true;
2767
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002768 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002769 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002770 return true;
2771
Daniel Sandersa736b372016-04-29 13:33:12 +00002772 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002773 }
2774 return false;
2775}
2776
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002777void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002778 const MCSubtargetInfo *STI, bool IsLoad,
2779 bool IsImmOpnd) {
2780 if (IsLoad) {
2781 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2782 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002783 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002784 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2785}
2786
2787void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2788 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2789 MipsTargetStreamer &TOut = getTargetStreamer();
2790
2791 unsigned DstReg = Inst.getOperand(0).getReg();
2792 unsigned BaseReg = Inst.getOperand(1).getReg();
2793
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002794 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002795 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2796 unsigned DstRegClassID =
2797 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2798 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2799 (DstRegClassID == Mips::GPR64RegClassID);
2800
2801 if (IsImmOpnd) {
2802 // Try to use DstReg as the temporary.
2803 if (IsGPR && (BaseReg != DstReg)) {
2804 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2805 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2806 STI);
2807 return;
2808 }
2809
Matheus Almeida7de68e72014-06-18 14:46:05 +00002810 // At this point we need AT to perform the expansions and we exit if it is
2811 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002812 unsigned ATReg = getATReg(IDLoc);
2813 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002814 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002815
2816 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2817 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2818 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002819 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002820
Daniel Sandersfba875f2016-04-29 13:43:45 +00002821 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002822 MCOperand LoOperand = MCOperand::createExpr(
2823 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2824 MCOperand HiOperand = MCOperand::createExpr(
2825 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002826
2827 // Try to use DstReg as the temporary.
2828 if (IsGPR && (BaseReg != DstReg)) {
2829 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2830 LoOperand, DstReg, IDLoc, STI);
2831 return;
2832 }
2833
2834 // At this point we need AT to perform the expansions and we exit if it is
2835 // not available.
2836 unsigned ATReg = getATReg(IDLoc);
2837 if (!ATReg)
2838 return;
2839
2840 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2841 LoOperand, ATReg, IDLoc, STI);
2842}
2843
2844void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2845 const MCSubtargetInfo *STI,
2846 bool IsImmOpnd) {
2847 MipsTargetStreamer &TOut = getTargetStreamer();
2848
2849 unsigned SrcReg = Inst.getOperand(0).getReg();
2850 unsigned BaseReg = Inst.getOperand(1).getReg();
2851
Daniel Sanders241c6792016-05-12 14:01:50 +00002852 if (IsImmOpnd) {
2853 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2854 Inst.getOperand(2).getImm(),
2855 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
2856 return;
2857 }
2858
Daniel Sandersfba875f2016-04-29 13:43:45 +00002859 unsigned ATReg = getATReg(IDLoc);
2860 if (!ATReg)
2861 return;
2862
Daniel Sandersfba875f2016-04-29 13:43:45 +00002863 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002864 MCOperand LoOperand = MCOperand::createExpr(
2865 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2866 MCOperand HiOperand = MCOperand::createExpr(
2867 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002868 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2869 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002870}
2871
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002872bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2873 MCStreamer &Out,
2874 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002875 unsigned OpNum = Inst.getNumOperands();
2876 unsigned Opcode = Inst.getOpcode();
2877 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2878
2879 assert (Inst.getOperand(OpNum - 1).isImm() &&
2880 Inst.getOperand(OpNum - 2).isReg() &&
2881 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2882
2883 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2884 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002885 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2886 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2887 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2888 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002889 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002890 if (inMicroMipsMode() && hasMips32r6())
2891 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2892 else
2893 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2894 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002895
2896 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002897 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002898 return false;
2899}
2900
Toma Tabacu1a108322015-06-17 13:20:24 +00002901bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002902 MCStreamer &Out,
2903 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002904 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002905 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002906 unsigned PseudoOpcode = Inst.getOpcode();
2907 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002908 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002909 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2910
2911 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002912 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002913
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002914 unsigned TrgReg;
2915 if (TrgOp.isReg())
2916 TrgReg = TrgOp.getReg();
2917 else if (TrgOp.isImm()) {
2918 warnIfNoMacro(IDLoc);
2919 EmittedNoMacroWarning = true;
2920
2921 TrgReg = getATReg(IDLoc);
2922 if (!TrgReg)
2923 return true;
2924
2925 switch(PseudoOpcode) {
2926 default:
2927 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2928 case Mips::BLTImmMacro:
2929 PseudoOpcode = Mips::BLT;
2930 break;
2931 case Mips::BLEImmMacro:
2932 PseudoOpcode = Mips::BLE;
2933 break;
2934 case Mips::BGEImmMacro:
2935 PseudoOpcode = Mips::BGE;
2936 break;
2937 case Mips::BGTImmMacro:
2938 PseudoOpcode = Mips::BGT;
2939 break;
2940 case Mips::BLTUImmMacro:
2941 PseudoOpcode = Mips::BLTU;
2942 break;
2943 case Mips::BLEUImmMacro:
2944 PseudoOpcode = Mips::BLEU;
2945 break;
2946 case Mips::BGEUImmMacro:
2947 PseudoOpcode = Mips::BGEU;
2948 break;
2949 case Mips::BGTUImmMacro:
2950 PseudoOpcode = Mips::BGTU;
2951 break;
2952 case Mips::BLTLImmMacro:
2953 PseudoOpcode = Mips::BLTL;
2954 break;
2955 case Mips::BLELImmMacro:
2956 PseudoOpcode = Mips::BLEL;
2957 break;
2958 case Mips::BGELImmMacro:
2959 PseudoOpcode = Mips::BGEL;
2960 break;
2961 case Mips::BGTLImmMacro:
2962 PseudoOpcode = Mips::BGTL;
2963 break;
2964 case Mips::BLTULImmMacro:
2965 PseudoOpcode = Mips::BLTUL;
2966 break;
2967 case Mips::BLEULImmMacro:
2968 PseudoOpcode = Mips::BLEUL;
2969 break;
2970 case Mips::BGEULImmMacro:
2971 PseudoOpcode = Mips::BGEUL;
2972 break;
2973 case Mips::BGTULImmMacro:
2974 PseudoOpcode = Mips::BGTUL;
2975 break;
2976 }
2977
2978 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002979 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002980 return true;
2981 }
2982
Toma Tabacu1a108322015-06-17 13:20:24 +00002983 switch (PseudoOpcode) {
2984 case Mips::BLT:
2985 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002986 case Mips::BLTL:
2987 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002988 AcceptsEquality = false;
2989 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002990 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2991 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002992 ZeroSrcOpcode = Mips::BGTZ;
2993 ZeroTrgOpcode = Mips::BLTZ;
2994 break;
2995 case Mips::BLE:
2996 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002997 case Mips::BLEL:
2998 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002999 AcceptsEquality = true;
3000 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003001 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3002 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003003 ZeroSrcOpcode = Mips::BGEZ;
3004 ZeroTrgOpcode = Mips::BLEZ;
3005 break;
3006 case Mips::BGE:
3007 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003008 case Mips::BGEL:
3009 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003010 AcceptsEquality = true;
3011 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003012 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3013 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003014 ZeroSrcOpcode = Mips::BLEZ;
3015 ZeroTrgOpcode = Mips::BGEZ;
3016 break;
3017 case Mips::BGT:
3018 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003019 case Mips::BGTL:
3020 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003021 AcceptsEquality = false;
3022 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003023 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3024 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003025 ZeroSrcOpcode = Mips::BLTZ;
3026 ZeroTrgOpcode = Mips::BGTZ;
3027 break;
3028 default:
3029 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3030 }
3031
Toma Tabacu1a108322015-06-17 13:20:24 +00003032 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3033 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3034 if (IsSrcRegZero && IsTrgRegZero) {
3035 // FIXME: All of these Opcode-specific if's are needed for compatibility
3036 // with GAS' behaviour. However, they may not generate the most efficient
3037 // code in some circumstances.
3038 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003039 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3040 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003041 return false;
3042 }
3043 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003044 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3045 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003046 Warning(IDLoc, "branch is always taken");
3047 return false;
3048 }
3049 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003050 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3051 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003052 Warning(IDLoc, "branch is always taken");
3053 return false;
3054 }
3055 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003056 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3057 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003058 return false;
3059 }
3060 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003061 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3062 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003063 return false;
3064 }
3065 if (AcceptsEquality) {
3066 // If both registers are $0 and the pseudo-branch accepts equality, it
3067 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003068 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3069 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003070 Warning(IDLoc, "branch is always taken");
3071 return false;
3072 }
3073 // If both registers are $0 and the pseudo-branch does not accept
3074 // equality, it will never be taken, so we don't have to emit anything.
3075 return false;
3076 }
3077 if (IsSrcRegZero || IsTrgRegZero) {
3078 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3079 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3080 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3081 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3082 // the pseudo-branch will never be taken, so we don't emit anything.
3083 // This only applies to unsigned pseudo-branches.
3084 return false;
3085 }
3086 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3087 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3088 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3089 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3090 // the pseudo-branch will always be taken, so we emit an unconditional
3091 // branch.
3092 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003093 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3094 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003095 Warning(IDLoc, "branch is always taken");
3096 return false;
3097 }
3098 if (IsUnsigned) {
3099 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3100 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3101 // the pseudo-branch will be taken only when the non-zero register is
3102 // different from 0, so we emit a BNEZ.
3103 //
3104 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3105 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3106 // the pseudo-branch will be taken only when the non-zero register is
3107 // equal to 0, so we emit a BEQZ.
3108 //
3109 // Because only BLEU and BGEU branch on equality, we can use the
3110 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003111 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3112 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3113 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003114 return false;
3115 }
3116 // If we have a signed pseudo-branch and one of the registers is $0,
3117 // we can use an appropriate compare-to-zero branch. We select which one
3118 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003119 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3120 IsSrcRegZero ? TrgReg : SrcReg,
3121 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003122 return false;
3123 }
3124
3125 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3126 // expansions. If it is not available, we return.
3127 unsigned ATRegNum = getATReg(IDLoc);
3128 if (!ATRegNum)
3129 return true;
3130
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003131 if (!EmittedNoMacroWarning)
3132 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003133
3134 // SLT fits well with 2 of our 4 pseudo-branches:
3135 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3136 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3137 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3138 // This is accomplished by using a BNEZ with the result of the SLT.
3139 //
3140 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3141 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3142 // Because only BGE and BLE branch on equality, we can use the
3143 // AcceptsEquality variable to decide when to emit the BEQZ.
3144 // Note that the order of the SLT arguments doesn't change between
3145 // opposites.
3146 //
3147 // The same applies to the unsigned variants, except that SLTu is used
3148 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003149 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3150 ReverseOrderSLT ? TrgReg : SrcReg,
3151 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003152
Daniel Sandersa736b372016-04-29 13:33:12 +00003153 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3154 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3155 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3156 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003157 return false;
3158}
3159
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003160bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3161 const MCSubtargetInfo *STI, const bool IsMips64,
3162 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003163 MipsTargetStreamer &TOut = getTargetStreamer();
3164
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003165 warnIfNoMacro(IDLoc);
3166
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003167 const MCOperand &RdRegOp = Inst.getOperand(0);
3168 assert(RdRegOp.isReg() && "expected register operand kind");
3169 unsigned RdReg = RdRegOp.getReg();
3170
3171 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003172 assert(RsRegOp.isReg() && "expected register operand kind");
3173 unsigned RsReg = RsRegOp.getReg();
3174
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003175 const MCOperand &RtRegOp = Inst.getOperand(2);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003176 assert(RtRegOp.isReg() && "expected register operand kind");
3177 unsigned RtReg = RtRegOp.getReg();
3178 unsigned DivOp;
3179 unsigned ZeroReg;
3180
3181 if (IsMips64) {
3182 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3183 ZeroReg = Mips::ZERO_64;
3184 } else {
3185 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3186 ZeroReg = Mips::ZERO;
3187 }
3188
3189 bool UseTraps = useTraps();
3190
3191 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
3192 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
3193 Warning(IDLoc, "dividing zero by zero");
3194 if (IsMips64) {
3195 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
3196 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003197 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003198 return false;
3199 }
3200
Daniel Sandersa736b372016-04-29 13:33:12 +00003201 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003202 return false;
3203 }
3204 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00003205 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003206 return false;
3207 }
3208 }
3209
3210 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3211 Warning(IDLoc, "division by zero");
3212 if (Signed) {
3213 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003214 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003215 return false;
3216 }
3217
Daniel Sandersa736b372016-04-29 13:33:12 +00003218 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003219 return false;
3220 }
3221 }
3222
3223 // FIXME: The values for these two BranchTarget variables may be different in
3224 // micromips. These magic numbers need to be removed.
3225 unsigned BranchTargetNoTraps;
3226 unsigned BranchTarget;
3227
3228 if (UseTraps) {
3229 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003230 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003231 } else {
3232 BranchTarget = IsMips64 ? 20 : 16;
3233 BranchTargetNoTraps = 8;
3234 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003235 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003236 }
3237
Daniel Sandersa736b372016-04-29 13:33:12 +00003238 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003239
3240 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003241 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003242
3243 if (!Signed) {
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003244 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003245 return false;
3246 }
3247
3248 unsigned ATReg = getATReg(IDLoc);
3249 if (!ATReg)
3250 return true;
3251
Daniel Sandersa736b372016-04-29 13:33:12 +00003252 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003253 if (IsMips64) {
3254 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003255 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3256 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3257 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003258 } else {
3259 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003260 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3261 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003262 }
3263
3264 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003265 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003266 else {
3267 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003268 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3269 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3270 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003271 }
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003272 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003273 return false;
3274}
3275
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003276bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003277 SMLoc IDLoc, MCStreamer &Out,
3278 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003279 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003280
3281 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3282 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3283 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3284
3285 unsigned FirstReg = Inst.getOperand(0).getReg();
3286 unsigned SecondReg = Inst.getOperand(1).getReg();
3287 unsigned ThirdReg = Inst.getOperand(2).getReg();
3288
3289 if (hasMips1() && !hasMips2()) {
3290 unsigned ATReg = getATReg(IDLoc);
3291 if (!ATReg)
3292 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003293 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3294 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3295 TOut.emitNop(IDLoc, STI);
3296 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3297 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3298 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3299 TOut.emitNop(IDLoc, STI);
3300 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3301 : Mips::CVT_W_S,
3302 FirstReg, SecondReg, IDLoc, STI);
3303 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3304 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003305 return false;
3306 }
3307
Daniel Sandersa736b372016-04-29 13:33:12 +00003308 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3309 : Mips::TRUNC_W_S,
3310 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003311
3312 return false;
3313}
3314
Daniel Sanders6394ee52015-10-15 14:52:58 +00003315bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003316 MCStreamer &Out, const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003317 MipsTargetStreamer &TOut = getTargetStreamer();
3318
Toma Tabacud88d79c2015-06-23 14:39:42 +00003319 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003320 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003321 }
3322
3323 warnIfNoMacro(IDLoc);
3324
3325 const MCOperand &DstRegOp = Inst.getOperand(0);
3326 assert(DstRegOp.isReg() && "expected register operand kind");
3327
3328 const MCOperand &SrcRegOp = Inst.getOperand(1);
3329 assert(SrcRegOp.isReg() && "expected register operand kind");
3330
3331 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3332 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3333
3334 unsigned DstReg = DstRegOp.getReg();
3335 unsigned SrcReg = SrcRegOp.getReg();
3336 int64_t OffsetValue = OffsetImmOp.getImm();
3337
3338 // NOTE: We always need AT for ULHU, as it is always used as the source
3339 // register for one of the LBu's.
3340 unsigned ATReg = getATReg(IDLoc);
3341 if (!ATReg)
3342 return true;
3343
3344 // When the value of offset+1 does not fit in 16 bits, we have to load the
3345 // offset in AT, (D)ADDu the original source register (if there was one), and
3346 // then use AT as the source register for the 2 generated LBu's.
3347 bool LoadedOffsetInAT = false;
3348 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3349 LoadedOffsetInAT = true;
3350
3351 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003352 true, IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003353 return true;
3354
3355 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3356 // because it will make our output more similar to GAS'. For example,
3357 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3358 // instead of just an "ori $1, $9, 32768".
3359 // NOTE: If there is no source register specified in the ULHU, the parser
3360 // will interpret it as $0.
3361 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003362 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003363 }
3364
3365 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3366 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3367 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3368
3369 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3370 if (isLittle()) {
3371 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3372 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3373 } else {
3374 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3375 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3376 }
3377
3378 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3379
Daniel Sandersa736b372016-04-29 13:33:12 +00003380 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3381 FirstLbuOffset, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003382
Daniel Sandersa736b372016-04-29 13:33:12 +00003383 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3384 STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003385
Daniel Sandersa736b372016-04-29 13:33:12 +00003386 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003387
Daniel Sandersa736b372016-04-29 13:33:12 +00003388 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003389
3390 return false;
3391}
3392
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003393bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3394 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003395 MipsTargetStreamer &TOut = getTargetStreamer();
3396
Nirav Dave2364748a2016-09-16 18:30:20 +00003397 if (hasMips32r6() || hasMips64r6())
3398 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003399
3400 const MCOperand &DstRegOp = Inst.getOperand(0);
3401 assert(DstRegOp.isReg() && "expected register operand kind");
3402
3403 const MCOperand &SrcRegOp = Inst.getOperand(1);
3404 assert(SrcRegOp.isReg() && "expected register operand kind");
3405
3406 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3407 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3408
3409 unsigned SrcReg = SrcRegOp.getReg();
3410 int64_t OffsetValue = OffsetImmOp.getImm();
3411 unsigned ATReg = 0;
3412
3413 // When the value of offset+3 does not fit in 16 bits, we have to load the
3414 // offset in AT, (D)ADDu the original source register (if there was one), and
3415 // then use AT as the source register for the generated LWL and LWR.
3416 bool LoadedOffsetInAT = false;
3417 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3418 ATReg = getATReg(IDLoc);
3419 if (!ATReg)
3420 return true;
3421 LoadedOffsetInAT = true;
3422
3423 warnIfNoMacro(IDLoc);
3424
3425 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003426 true, IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003427 return true;
3428
3429 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3430 // because it will make our output more similar to GAS'. For example,
3431 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3432 // instead of just an "ori $1, $9, 32768".
3433 // NOTE: If there is no source register specified in the ULW, the parser
3434 // will interpret it as $0.
3435 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003436 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003437 }
3438
3439 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3440 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3441 if (isLittle()) {
3442 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3443 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3444 } else {
3445 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3446 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3447 }
3448
Daniel Sandersa736b372016-04-29 13:33:12 +00003449 TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3450 STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003451
Daniel Sandersa736b372016-04-29 13:33:12 +00003452 TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
3453 IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003454
3455 return false;
3456}
3457
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003458bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003459 MCStreamer &Out,
3460 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003461 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003462
3463 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3464 assert (Inst.getOperand(0).isReg() &&
3465 Inst.getOperand(1).isReg() &&
3466 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3467
3468 unsigned ATReg = Mips::NoRegister;
3469 unsigned FinalDstReg = Mips::NoRegister;
3470 unsigned DstReg = Inst.getOperand(0).getReg();
3471 unsigned SrcReg = Inst.getOperand(1).getReg();
3472 int64_t ImmValue = Inst.getOperand(2).getImm();
3473
3474 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3475
3476 unsigned FinalOpcode = Inst.getOpcode();
3477
3478 if (DstReg == SrcReg) {
3479 ATReg = getATReg(Inst.getLoc());
3480 if (!ATReg)
3481 return true;
3482 FinalDstReg = DstReg;
3483 DstReg = ATReg;
3484 }
3485
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003486 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003487 switch (FinalOpcode) {
3488 default:
3489 llvm_unreachable("unimplemented expansion");
3490 case (Mips::ADDi):
3491 FinalOpcode = Mips::ADD;
3492 break;
3493 case (Mips::ADDiu):
3494 FinalOpcode = Mips::ADDu;
3495 break;
3496 case (Mips::ANDi):
3497 FinalOpcode = Mips::AND;
3498 break;
3499 case (Mips::NORImm):
3500 FinalOpcode = Mips::NOR;
3501 break;
3502 case (Mips::ORi):
3503 FinalOpcode = Mips::OR;
3504 break;
3505 case (Mips::SLTi):
3506 FinalOpcode = Mips::SLT;
3507 break;
3508 case (Mips::SLTiu):
3509 FinalOpcode = Mips::SLTu;
3510 break;
3511 case (Mips::XORi):
3512 FinalOpcode = Mips::XOR;
3513 break;
3514 }
3515
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003516 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003517 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003518 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003519 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003520 return false;
3521 }
3522 return true;
3523}
3524
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003525bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3526 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003527 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003528 unsigned ATReg = Mips::NoRegister;
3529 unsigned DReg = Inst.getOperand(0).getReg();
3530 unsigned SReg = Inst.getOperand(1).getReg();
3531 unsigned TReg = Inst.getOperand(2).getReg();
3532 unsigned TmpReg = DReg;
3533
3534 unsigned FirstShift = Mips::NOP;
3535 unsigned SecondShift = Mips::NOP;
3536
3537 if (hasMips32r2()) {
3538
3539 if (DReg == SReg) {
3540 TmpReg = getATReg(Inst.getLoc());
3541 if (!TmpReg)
3542 return true;
3543 }
3544
3545 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003546 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3547 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003548 return false;
3549 }
3550
3551 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003552 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003553 return false;
3554 }
3555
3556 return true;
3557 }
3558
3559 if (hasMips32()) {
3560
3561 switch (Inst.getOpcode()) {
3562 default:
3563 llvm_unreachable("unexpected instruction opcode");
3564 case Mips::ROL:
3565 FirstShift = Mips::SRLV;
3566 SecondShift = Mips::SLLV;
3567 break;
3568 case Mips::ROR:
3569 FirstShift = Mips::SLLV;
3570 SecondShift = Mips::SRLV;
3571 break;
3572 }
3573
3574 ATReg = getATReg(Inst.getLoc());
3575 if (!ATReg)
3576 return true;
3577
Daniel Sandersa736b372016-04-29 13:33:12 +00003578 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3579 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3580 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3581 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003582
3583 return false;
3584 }
3585
3586 return true;
3587}
3588
3589bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003590 MCStreamer &Out,
3591 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003592 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003593 unsigned ATReg = Mips::NoRegister;
3594 unsigned DReg = Inst.getOperand(0).getReg();
3595 unsigned SReg = Inst.getOperand(1).getReg();
3596 int64_t ImmValue = Inst.getOperand(2).getImm();
3597
3598 unsigned FirstShift = Mips::NOP;
3599 unsigned SecondShift = Mips::NOP;
3600
3601 if (hasMips32r2()) {
3602
3603 if (Inst.getOpcode() == Mips::ROLImm) {
3604 uint64_t MaxShift = 32;
3605 uint64_t ShiftValue = ImmValue;
3606 if (ImmValue != 0)
3607 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003608 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003609 return false;
3610 }
3611
3612 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003613 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003614 return false;
3615 }
3616
3617 return true;
3618 }
3619
3620 if (hasMips32()) {
3621
3622 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003623 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003624 return false;
3625 }
3626
3627 switch (Inst.getOpcode()) {
3628 default:
3629 llvm_unreachable("unexpected instruction opcode");
3630 case Mips::ROLImm:
3631 FirstShift = Mips::SLL;
3632 SecondShift = Mips::SRL;
3633 break;
3634 case Mips::RORImm:
3635 FirstShift = Mips::SRL;
3636 SecondShift = Mips::SLL;
3637 break;
3638 }
3639
3640 ATReg = getATReg(Inst.getLoc());
3641 if (!ATReg)
3642 return true;
3643
Daniel Sandersa736b372016-04-29 13:33:12 +00003644 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3645 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3646 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003647
3648 return false;
3649 }
3650
3651 return true;
3652}
3653
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003654bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3655 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003656 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003657 unsigned ATReg = Mips::NoRegister;
3658 unsigned DReg = Inst.getOperand(0).getReg();
3659 unsigned SReg = Inst.getOperand(1).getReg();
3660 unsigned TReg = Inst.getOperand(2).getReg();
3661 unsigned TmpReg = DReg;
3662
3663 unsigned FirstShift = Mips::NOP;
3664 unsigned SecondShift = Mips::NOP;
3665
3666 if (hasMips64r2()) {
3667
3668 if (TmpReg == SReg) {
3669 TmpReg = getATReg(Inst.getLoc());
3670 if (!TmpReg)
3671 return true;
3672 }
3673
3674 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003675 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3676 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003677 return false;
3678 }
3679
3680 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003681 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003682 return false;
3683 }
3684
3685 return true;
3686 }
3687
3688 if (hasMips64()) {
3689
3690 switch (Inst.getOpcode()) {
3691 default:
3692 llvm_unreachable("unexpected instruction opcode");
3693 case Mips::DROL:
3694 FirstShift = Mips::DSRLV;
3695 SecondShift = Mips::DSLLV;
3696 break;
3697 case Mips::DROR:
3698 FirstShift = Mips::DSLLV;
3699 SecondShift = Mips::DSRLV;
3700 break;
3701 }
3702
3703 ATReg = getATReg(Inst.getLoc());
3704 if (!ATReg)
3705 return true;
3706
Daniel Sandersa736b372016-04-29 13:33:12 +00003707 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3708 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3709 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3710 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003711
3712 return false;
3713 }
3714
3715 return true;
3716}
3717
3718bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003719 MCStreamer &Out,
3720 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003721 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003722 unsigned ATReg = Mips::NoRegister;
3723 unsigned DReg = Inst.getOperand(0).getReg();
3724 unsigned SReg = Inst.getOperand(1).getReg();
3725 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3726
3727 unsigned FirstShift = Mips::NOP;
3728 unsigned SecondShift = Mips::NOP;
3729
3730 MCInst TmpInst;
3731
3732 if (hasMips64r2()) {
3733
3734 unsigned FinalOpcode = Mips::NOP;
3735 if (ImmValue == 0)
3736 FinalOpcode = Mips::DROTR;
3737 else if (ImmValue % 32 == 0)
3738 FinalOpcode = Mips::DROTR32;
3739 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3740 if (Inst.getOpcode() == Mips::DROLImm)
3741 FinalOpcode = Mips::DROTR32;
3742 else
3743 FinalOpcode = Mips::DROTR;
3744 } else if (ImmValue >= 33) {
3745 if (Inst.getOpcode() == Mips::DROLImm)
3746 FinalOpcode = Mips::DROTR;
3747 else
3748 FinalOpcode = Mips::DROTR32;
3749 }
3750
3751 uint64_t ShiftValue = ImmValue % 32;
3752 if (Inst.getOpcode() == Mips::DROLImm)
3753 ShiftValue = (32 - ImmValue % 32) % 32;
3754
Daniel Sandersa736b372016-04-29 13:33:12 +00003755 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003756
3757 return false;
3758 }
3759
3760 if (hasMips64()) {
3761
3762 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003763 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003764 return false;
3765 }
3766
3767 switch (Inst.getOpcode()) {
3768 default:
3769 llvm_unreachable("unexpected instruction opcode");
3770 case Mips::DROLImm:
3771 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3772 FirstShift = Mips::DSLL;
3773 SecondShift = Mips::DSRL32;
3774 }
3775 if (ImmValue == 32) {
3776 FirstShift = Mips::DSLL32;
3777 SecondShift = Mips::DSRL32;
3778 }
3779 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3780 FirstShift = Mips::DSLL32;
3781 SecondShift = Mips::DSRL;
3782 }
3783 break;
3784 case Mips::DRORImm:
3785 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3786 FirstShift = Mips::DSRL;
3787 SecondShift = Mips::DSLL32;
3788 }
3789 if (ImmValue == 32) {
3790 FirstShift = Mips::DSRL32;
3791 SecondShift = Mips::DSLL32;
3792 }
3793 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3794 FirstShift = Mips::DSRL32;
3795 SecondShift = Mips::DSLL;
3796 }
3797 break;
3798 }
3799
3800 ATReg = getATReg(Inst.getLoc());
3801 if (!ATReg)
3802 return true;
3803
Daniel Sandersa736b372016-04-29 13:33:12 +00003804 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3805 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3806 Inst.getLoc(), STI);
3807 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003808
3809 return false;
3810 }
3811
3812 return true;
3813}
3814
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003815bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3816 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003817 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003818 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3819 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3820
Daniel Sandersa736b372016-04-29 13:33:12 +00003821 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003822 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003823 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003824 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003825 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3826 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003827
3828 return false;
3829}
3830
Simon Dardisaff4d142016-10-18 14:28:00 +00003831static unsigned nextReg(unsigned Reg) {
3832 switch (Reg) {
3833 case Mips::ZERO: return Mips::AT;
3834 case Mips::AT: return Mips::V0;
3835 case Mips::V0: return Mips::V1;
3836 case Mips::V1: return Mips::A0;
3837 case Mips::A0: return Mips::A1;
3838 case Mips::A1: return Mips::A2;
3839 case Mips::A2: return Mips::A3;
3840 case Mips::A3: return Mips::T0;
3841 case Mips::T0: return Mips::T1;
3842 case Mips::T1: return Mips::T2;
3843 case Mips::T2: return Mips::T3;
3844 case Mips::T3: return Mips::T4;
3845 case Mips::T4: return Mips::T5;
3846 case Mips::T5: return Mips::T6;
3847 case Mips::T6: return Mips::T7;
3848 case Mips::T7: return Mips::S0;
3849 case Mips::S0: return Mips::S1;
3850 case Mips::S1: return Mips::S2;
3851 case Mips::S2: return Mips::S3;
3852 case Mips::S3: return Mips::S4;
3853 case Mips::S4: return Mips::S5;
3854 case Mips::S5: return Mips::S6;
3855 case Mips::S6: return Mips::S7;
3856 case Mips::S7: return Mips::T8;
3857 case Mips::T8: return Mips::T9;
3858 case Mips::T9: return Mips::K0;
3859 case Mips::K0: return Mips::K1;
3860 case Mips::K1: return Mips::GP;
3861 case Mips::GP: return Mips::SP;
3862 case Mips::SP: return Mips::FP;
3863 case Mips::FP: return Mips::RA;
3864 case Mips::RA: return Mips::ZERO;
3865 default: return 0;
3866 }
3867
3868}
3869
3870// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
3871// lw $<reg+1>>, offset+4($reg2)'
3872// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
3873// sw $<reg+1>>, offset+4($reg2)'
3874// for O32.
3875bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
3876 MCStreamer &Out,
3877 const MCSubtargetInfo *STI,
3878 bool IsLoad) {
3879 if (!isABI_O32())
3880 return true;
3881
3882 warnIfNoMacro(IDLoc);
3883
3884 MipsTargetStreamer &TOut = getTargetStreamer();
3885 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
3886 unsigned FirstReg = Inst.getOperand(0).getReg();
3887 unsigned SecondReg = nextReg(FirstReg);
3888 unsigned BaseReg = Inst.getOperand(1).getReg();
3889 if (!SecondReg)
3890 return true;
3891
3892 warnIfRegIndexIsAT(FirstReg, IDLoc);
3893
3894 assert(Inst.getOperand(2).isImm() &&
3895 "Offset for load macro is not immediate!");
3896
3897 MCOperand &FirstOffset = Inst.getOperand(2);
3898 signed NextOffset = FirstOffset.getImm() + 4;
3899 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
3900
3901 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
3902 return true;
3903
3904 // For loads, clobber the base register with the second load instead of the
3905 // first if the BaseReg == FirstReg.
3906 if (FirstReg != BaseReg || !IsLoad) {
3907 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
3908 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
3909 } else {
3910 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
3911 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
3912 }
3913
3914 return false;
3915}
3916
Daniel Sandersc5537422016-07-27 13:49:44 +00003917unsigned
3918MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
3919 const OperandVector &Operands) {
3920 switch (Inst.getOpcode()) {
3921 default:
3922 return Match_Success;
3923 case Mips::DATI:
3924 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00003925 case Mips::DATI_MM64R6:
3926 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00003927 if (static_cast<MipsOperand &>(*Operands[1])
3928 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
3929 return Match_Success;
3930 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00003931 }
3932}
Matheus Almeida595fcab2014-06-11 15:05:56 +00003933unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00003934 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00003935 // As described by the MIPSR6 spec, daui must not use the zero operand for
3936 // its source operand.
3937 case Mips::DAUI:
3938 case Mips::DAUI_MM64R6:
3939 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
3940 Inst.getOperand(1).getReg() == Mips::ZERO_64)
3941 return Match_RequiresNoZeroRegister;
3942 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00003943 // As described by the Mips32r2 spec, the registers Rd and Rs for
3944 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00003945 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00003946 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00003947 case Mips::JALR_HB:
3948 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00003949 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00003950 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
3951 return Match_RequiresDifferentSrcAndDst;
3952 return Match_Success;
3953 case Mips::LWP_MM:
3954 case Mips::LWP_MMR6:
3955 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
3956 return Match_RequiresDifferentSrcAndDst;
3957 return Match_Success;
3958 // As described the MIPSR6 spec, the compact branches that compare registers
3959 // must:
3960 // a) Not use the zero register.
3961 // b) Not use the same register twice.
3962 // c) rs < rt for bnec, beqc.
3963 // NB: For this case, the encoding will swap the operands as their
3964 // ordering doesn't matter. GAS performs this transformation too.
3965 // Hence, that constraint does not have to be enforced.
3966 //
3967 // The compact branches that branch iff the signed addition of two registers
3968 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
3969 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00003970 case Mips::BLEZC: case Mips::BLEZC_MMR6:
3971 case Mips::BGEZC: case Mips::BGEZC_MMR6:
3972 case Mips::BGTZC: case Mips::BGTZC_MMR6:
3973 case Mips::BLTZC: case Mips::BLTZC_MMR6:
3974 case Mips::BEQZC: case Mips::BEQZC_MMR6:
3975 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00003976 case Mips::BLEZC64:
3977 case Mips::BGEZC64:
3978 case Mips::BGTZC64:
3979 case Mips::BLTZC64:
3980 case Mips::BEQZC64:
3981 case Mips::BNEZC64:
3982 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
3983 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00003984 return Match_RequiresNoZeroRegister;
3985 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00003986 case Mips::BGEC: case Mips::BGEC_MMR6:
3987 case Mips::BLTC: case Mips::BLTC_MMR6:
3988 case Mips::BGEUC: case Mips::BGEUC_MMR6:
3989 case Mips::BLTUC: case Mips::BLTUC_MMR6:
3990 case Mips::BEQC: case Mips::BEQC_MMR6:
3991 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00003992 case Mips::BGEC64:
3993 case Mips::BLTC64:
3994 case Mips::BGEUC64:
3995 case Mips::BLTUC64:
3996 case Mips::BEQC64:
3997 case Mips::BNEC64:
3998 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
3999 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004000 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00004001 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4002 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004003 return Match_RequiresNoZeroRegister;
4004 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4005 return Match_RequiresDifferentOperands;
4006 return Match_Success;
4007 default:
4008 return Match_Success;
4009 }
Matheus Almeida595fcab2014-06-11 15:05:56 +00004010}
4011
Daniel Sanders52da7af2015-11-06 12:11:03 +00004012static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
4013 uint64_t ErrorInfo) {
4014 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
4015 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
4016 if (ErrorLoc == SMLoc())
4017 return Loc;
4018 return ErrorLoc;
4019 }
4020 return Loc;
4021}
4022
David Blaikie960ea3f2014-06-08 16:18:35 +00004023bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4024 OperandVector &Operands,
4025 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004026 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00004027 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00004028
Jack Carterb4dbc172012-09-05 23:34:03 +00004029 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00004030 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004031 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00004032
4033 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004034 case Match_Success: {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004035 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00004036 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004037 return false;
4038 }
4039 case Match_MissingFeature:
4040 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4041 return true;
4042 case Match_InvalidOperand: {
4043 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00004044 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004045 if (ErrorInfo >= Operands.size())
4046 return Error(IDLoc, "too few operands for instruction");
4047
Daniel Sanders52da7af2015-11-06 12:11:03 +00004048 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00004049 if (ErrorLoc == SMLoc())
4050 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00004051 }
4052
4053 return Error(ErrorLoc, "invalid operand for instruction");
4054 }
4055 case Match_MnemonicFail:
4056 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00004057 case Match_RequiresDifferentSrcAndDst:
4058 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00004059 case Match_RequiresDifferentOperands:
4060 return Error(IDLoc, "registers must be different");
4061 case Match_RequiresNoZeroRegister:
4062 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00004063 case Match_RequiresSameSrcAndDst:
4064 return Error(IDLoc, "source and destination must match");
Daniel Sanders52da7af2015-11-06 12:11:03 +00004065 case Match_Immz:
4066 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004067 case Match_UImm1_0:
4068 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4069 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00004070 case Match_UImm2_0:
4071 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4072 "expected 2-bit unsigned immediate");
4073 case Match_UImm2_1:
4074 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4075 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00004076 case Match_UImm3_0:
4077 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4078 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004079 case Match_UImm4_0:
4080 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4081 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00004082 case Match_SImm4_0:
4083 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4084 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004085 case Match_UImm5_0:
4086 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4087 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00004088 case Match_SImm5_0:
4089 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4090 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004091 case Match_UImm5_1:
4092 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4093 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004094 case Match_UImm5_32:
4095 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4096 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004097 case Match_UImm5_33:
4098 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4099 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004100 case Match_UImm5_0_Report_UImm6:
4101 // This is used on UImm5 operands that have a corresponding UImm5_32
4102 // operand to avoid confusing the user.
4103 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4104 "expected 6-bit unsigned immediate");
4105 case Match_UImm5_Lsl2:
4106 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4107 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00004108 case Match_UImmRange2_64:
4109 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4110 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00004111 case Match_UImm6_0:
4112 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4113 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00004114 case Match_UImm6_Lsl2:
4115 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4116 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00004117 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00004118 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4119 "expected 6-bit signed immediate");
4120 case Match_UImm7_0:
4121 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4122 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00004123 case Match_UImm7_N1:
4124 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4125 "expected immediate in range -1 .. 126");
4126 case Match_SImm7_Lsl2:
4127 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4128 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00004129 case Match_UImm8_0:
4130 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4131 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00004132 case Match_UImm10_0:
4133 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4134 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00004135 case Match_SImm10_0:
4136 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4137 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00004138 case Match_SImm11_0:
4139 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4140 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00004141 case Match_UImm16:
4142 case Match_UImm16_Relaxed:
4143 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4144 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004145 case Match_SImm16:
4146 case Match_SImm16_Relaxed:
4147 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4148 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00004149 case Match_SImm19_Lsl2:
4150 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4151 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00004152 case Match_UImm20_0:
4153 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4154 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00004155 case Match_UImm26_0:
4156 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4157 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00004158 case Match_SImm32:
4159 case Match_SImm32_Relaxed:
4160 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4161 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00004162 case Match_UImm32_Coerced:
4163 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4164 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00004165 case Match_MemSImm9:
4166 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4167 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00004168 case Match_MemSImm10:
4169 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4170 "expected memory with 10-bit signed offset");
4171 case Match_MemSImm10Lsl1:
4172 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4173 "expected memory with 11-bit signed offset and multiple of 2");
4174 case Match_MemSImm10Lsl2:
4175 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4176 "expected memory with 12-bit signed offset and multiple of 4");
4177 case Match_MemSImm10Lsl3:
4178 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4179 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00004180 case Match_MemSImm11:
4181 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4182 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00004183 case Match_MemSImm12:
4184 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4185 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004186 case Match_MemSImm16:
4187 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4188 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00004189 }
Craig Topper589ceee2015-01-03 08:16:34 +00004190
4191 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00004192}
4193
Toma Tabacud9d344b2015-04-27 14:05:04 +00004194void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
4195 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
4196 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
4197 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004198}
4199
Toma Tabacu81496c12015-05-20 08:54:45 +00004200void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
4201 if (!AssemblerOptions.back()->isMacro())
4202 Warning(Loc, "macro instruction expanded into multiple instructions");
4203}
4204
Daniel Sandersef638fe2014-10-03 15:37:37 +00004205void
4206MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
4207 SMRange Range, bool ShowColors) {
4208 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00004209 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00004210 ShowColors);
4211}
4212
Jack Carter1ac53222013-02-20 23:11:17 +00004213int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004214 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004215
Vladimir Medic4c299852013-11-06 11:27:05 +00004216 CC = StringSwitch<unsigned>(Name)
4217 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004218 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00004219 .Case("a0", 4)
4220 .Case("a1", 5)
4221 .Case("a2", 6)
4222 .Case("a3", 7)
4223 .Case("v0", 2)
4224 .Case("v1", 3)
4225 .Case("s0", 16)
4226 .Case("s1", 17)
4227 .Case("s2", 18)
4228 .Case("s3", 19)
4229 .Case("s4", 20)
4230 .Case("s5", 21)
4231 .Case("s6", 22)
4232 .Case("s7", 23)
4233 .Case("k0", 26)
4234 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004235 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00004236 .Case("sp", 29)
4237 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004238 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00004239 .Case("ra", 31)
4240 .Case("t0", 8)
4241 .Case("t1", 9)
4242 .Case("t2", 10)
4243 .Case("t3", 11)
4244 .Case("t4", 12)
4245 .Case("t5", 13)
4246 .Case("t6", 14)
4247 .Case("t7", 15)
4248 .Case("t8", 24)
4249 .Case("t9", 25)
4250 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004251
Toma Tabacufda445c2014-09-15 15:33:01 +00004252 if (!(isABI_N32() || isABI_N64()))
4253 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004254
Daniel Sandersef638fe2014-10-03 15:37:37 +00004255 if (12 <= CC && CC <= 15) {
4256 // Name is one of t4-t7
4257 AsmToken RegTok = getLexer().peekTok();
4258 SMRange RegRange = RegTok.getLocRange();
4259
4260 StringRef FixedName = StringSwitch<StringRef>(Name)
4261 .Case("t4", "t0")
4262 .Case("t5", "t1")
4263 .Case("t6", "t2")
4264 .Case("t7", "t3")
4265 .Default("");
4266 assert(FixedName != "" && "Register name is not one of t4-t7.");
4267
4268 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
4269 "Did you mean $" + FixedName + "?", RegRange);
4270 }
4271
Toma Tabacufda445c2014-09-15 15:33:01 +00004272 // Although SGI documentation just cuts out t0-t3 for n32/n64,
4273 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
4274 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
4275 if (8 <= CC && CC <= 11)
4276 CC += 4;
4277
4278 if (CC == -1)
4279 CC = StringSwitch<unsigned>(Name)
4280 .Case("a4", 8)
4281 .Case("a5", 9)
4282 .Case("a6", 10)
4283 .Case("a7", 11)
4284 .Case("kt0", 26)
4285 .Case("kt1", 27)
4286 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004287
4288 return CC;
4289}
Jack Carterd0bd6422013-04-18 00:41:53 +00004290
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004291int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
4292 int CC;
4293
4294 CC = StringSwitch<unsigned>(Name)
4295 .Case("hwr_cpunum", 0)
4296 .Case("hwr_synci_step", 1)
4297 .Case("hwr_cc", 2)
4298 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00004299 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004300 .Default(-1);
4301
4302 return CC;
4303}
4304
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004305int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004306
Jack Cartera63b16a2012-09-07 00:23:42 +00004307 if (Name[0] == 'f') {
4308 StringRef NumString = Name.substr(1);
4309 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004310 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004311 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004312 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00004313 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004314 return IntVal;
4315 }
4316 return -1;
4317}
Jack Cartera63b16a2012-09-07 00:23:42 +00004318
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004319int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
4320
4321 if (Name.startswith("fcc")) {
4322 StringRef NumString = Name.substr(3);
4323 unsigned IntVal;
4324 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004325 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004326 if (IntVal > 7) // There are only 8 fcc registers.
4327 return -1;
4328 return IntVal;
4329 }
4330 return -1;
4331}
4332
4333int MipsAsmParser::matchACRegisterName(StringRef Name) {
4334
Akira Hatanaka274d24c2013-08-14 01:15:52 +00004335 if (Name.startswith("ac")) {
4336 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004337 unsigned IntVal;
4338 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004339 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004340 if (IntVal > 3) // There are only 3 acc registers.
4341 return -1;
4342 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00004343 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004344 return -1;
4345}
Jack Carterd0bd6422013-04-18 00:41:53 +00004346
Jack Carter5dc8ac92013-09-25 23:50:44 +00004347int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
4348 unsigned IntVal;
4349
4350 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
4351 return -1;
4352
4353 if (IntVal > 31)
4354 return -1;
4355
4356 return IntVal;
4357}
4358
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004359int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
4360 int CC;
4361
4362 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00004363 .Case("msair", 0)
4364 .Case("msacsr", 1)
4365 .Case("msaaccess", 2)
4366 .Case("msasave", 3)
4367 .Case("msamodify", 4)
4368 .Case("msarequest", 5)
4369 .Case("msamap", 6)
4370 .Case("msaunmap", 7)
4371 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004372
4373 return CC;
4374}
4375
Toma Tabacu89a712b2015-04-15 10:48:56 +00004376unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004377 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004378 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004379 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004380 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004381 return 0;
4382 }
4383 unsigned AT = getReg(
4384 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004385 return AT;
4386}
Jack Carter0b744b32012-10-04 02:29:46 +00004387
Jack Carterd0bd6422013-04-18 00:41:53 +00004388unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004389 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004390}
4391
Toma Tabacu13964452014-09-04 13:23:44 +00004392bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004393 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004394 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004395
Jack Carter30a59822012-10-04 04:03:53 +00004396 // Check if the current operand has a custom associated parser, if so, try to
4397 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004398 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4399 if (ResTy == MatchOperand_Success)
4400 return false;
4401 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4402 // there was a match, but an error occurred, in which case, just return that
4403 // the operand parsing failed.
4404 if (ResTy == MatchOperand_ParseFail)
4405 return true;
4406
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004407 DEBUG(dbgs() << ".. Generic Parser\n");
4408
Jack Carterb4dbc172012-09-05 23:34:03 +00004409 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004410 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004411 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004412 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004413
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004414 // Almost all registers have been parsed by custom parsers. There is only
4415 // one exception to this. $zero (and it's alias $0) will reach this point
4416 // for div, divu, and similar instructions because it is not an operand
4417 // to the instruction definition but an explicit register. Special case
4418 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004419 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004420 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004421
Jack Carterd0bd6422013-04-18 00:41:53 +00004422 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004423 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004424 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004425 return true;
4426
Jack Carter873c7242013-01-12 01:03:14 +00004427 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004428 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004429 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004430 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004431 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004432
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004433 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004434 return false;
4435 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004436 default: {
4437 DEBUG(dbgs() << ".. generic integer expression\n");
4438
4439 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00004440 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004441 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004442 return true;
4443
Jack Carter873c7242013-01-12 01:03:14 +00004444 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4445
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004446 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004447 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004448 }
Jack Carter0b744b32012-10-04 02:29:46 +00004449 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004450 return true;
4451}
4452
Jack Carterb5cf5902013-04-17 00:18:04 +00004453bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4454
4455 switch (Expr->getKind()) {
4456 case MCExpr::Constant:
4457 return true;
4458 case MCExpr::SymbolRef:
4459 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4460 case MCExpr::Binary:
4461 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4462 if (!isEvaluated(BE->getLHS()))
4463 return false;
4464 return isEvaluated(BE->getRHS());
4465 }
4466 case MCExpr::Unary:
4467 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004468 case MCExpr::Target:
4469 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004470 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004471 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004472}
Jack Carterd0bd6422013-04-18 00:41:53 +00004473
Jack Carterb4dbc172012-09-05 23:34:03 +00004474bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4475 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004476 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004477 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004478 if (ResTy == MatchOperand_Success) {
4479 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004480 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004481 StartLoc = Operand.getStartLoc();
4482 EndLoc = Operand.getEndLoc();
4483
4484 // AFAIK, we only support numeric registers and named GPR's in CFI
4485 // directives.
4486 // Don't worry about eating tokens before failing. Using an unrecognised
4487 // register is a parse error.
4488 if (Operand.isGPRAsmReg()) {
4489 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004490 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004491 }
4492
4493 return (RegNo == (unsigned)-1);
4494 }
4495
4496 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004497 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004498}
4499
Jack Carterb5cf5902013-04-17 00:18:04 +00004500bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00004501 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004502
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004503 if (isParenExpr)
4504 return getParser().parseParenExprOfDepth(0, Res, S);
4505 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004506}
4507
David Blaikie960ea3f2014-06-08 16:18:35 +00004508MipsAsmParser::OperandMatchResultTy
4509MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004510 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004511 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004512 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004513 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004514 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004515 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004516 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004517 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004518
Jack Carterb5cf5902013-04-17 00:18:04 +00004519 if (getLexer().getKind() == AsmToken::LParen) {
4520 Parser.Lex();
4521 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004522 }
4523
Jack Carterb5cf5902013-04-17 00:18:04 +00004524 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004525 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004526 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004527
Jack Carterd0bd6422013-04-18 00:41:53 +00004528 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004529 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004530 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004531 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004532 SMLoc E =
4533 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004534 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004535 return MatchOperand_Success;
4536 }
4537 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004538 SMLoc E =
4539 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004540
Jack Carterd0bd6422013-04-18 00:41:53 +00004541 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004542 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00004543 auto Base = MipsOperand::createGPRReg(
4544 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00004545 Operands.push_back(
4546 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004547 return MatchOperand_Success;
4548 }
4549 Error(Parser.getTok().getLoc(), "'(' expected");
4550 return MatchOperand_ParseFail;
4551 }
4552
Jack Carterd0bd6422013-04-18 00:41:53 +00004553 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004554 }
4555
Toma Tabacu13964452014-09-04 13:23:44 +00004556 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004557 if (Res != MatchOperand_Success)
4558 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004559
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004560 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004561 Error(Parser.getTok().getLoc(), "')' expected");
4562 return MatchOperand_ParseFail;
4563 }
4564
Jack Carter873c7242013-01-12 01:03:14 +00004565 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4566
Jack Carterd0bd6422013-04-18 00:41:53 +00004567 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004568
Craig Topper062a2ba2014-04-25 05:30:21 +00004569 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004570 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004571
Jack Carterd0bd6422013-04-18 00:41:53 +00004572 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004573 std::unique_ptr<MipsOperand> op(
4574 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004575 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004576 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004577 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004578 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004579 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4580 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004581 if (IdVal->evaluateAsAbsolute(Imm))
4582 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004583 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004584 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004585 getContext());
4586 }
4587
David Blaikie960ea3f2014-06-08 16:18:35 +00004588 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004589 return MatchOperand_Success;
4590}
4591
David Blaikie960ea3f2014-06-08 16:18:35 +00004592bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004593 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004594 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004595 if (Sym) {
4596 SMLoc S = Parser.getTok().getLoc();
4597 const MCExpr *Expr;
4598 if (Sym->isVariable())
4599 Expr = Sym->getVariableValue();
4600 else
4601 return false;
4602 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004603 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004604 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004605 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004606 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004607 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004608 if (ResTy == MatchOperand_Success) {
4609 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004610 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004611 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004612 llvm_unreachable("Should never ParseFail");
4613 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004614 }
Jack Carterd76b2372013-03-21 21:44:16 +00004615 }
4616 }
4617 return false;
4618}
Jack Carterd0bd6422013-04-18 00:41:53 +00004619
Jack Carter873c7242013-01-12 01:03:14 +00004620MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004621MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004622 StringRef Identifier,
4623 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004624 int Index = matchCPURegisterName(Identifier);
4625 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004626 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004627 Index, Identifier, getContext().getRegisterInfo(), S,
4628 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004629 return MatchOperand_Success;
4630 }
4631
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004632 Index = matchHWRegsRegisterName(Identifier);
4633 if (Index != -1) {
4634 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004635 Index, Identifier, getContext().getRegisterInfo(), S,
4636 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004637 return MatchOperand_Success;
4638 }
4639
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004640 Index = matchFPURegisterName(Identifier);
4641 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004642 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004643 Index, Identifier, getContext().getRegisterInfo(), S,
4644 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004645 return MatchOperand_Success;
4646 }
4647
4648 Index = matchFCCRegisterName(Identifier);
4649 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004650 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004651 Index, Identifier, getContext().getRegisterInfo(), S,
4652 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004653 return MatchOperand_Success;
4654 }
4655
4656 Index = matchACRegisterName(Identifier);
4657 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004658 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004659 Index, Identifier, getContext().getRegisterInfo(), S,
4660 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004661 return MatchOperand_Success;
4662 }
4663
4664 Index = matchMSA128RegisterName(Identifier);
4665 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004666 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004667 Index, Identifier, getContext().getRegisterInfo(), S,
4668 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004669 return MatchOperand_Success;
4670 }
4671
4672 Index = matchMSA128CtrlRegisterName(Identifier);
4673 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004674 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004675 Index, Identifier, getContext().getRegisterInfo(), S,
4676 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004677 return MatchOperand_Success;
4678 }
4679
4680 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004681}
4682
4683MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004684MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004685 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004686 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004687
4688 if (Token.is(AsmToken::Identifier)) {
4689 DEBUG(dbgs() << ".. identifier\n");
4690 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004691 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004692 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004693 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004694 } else if (Token.is(AsmToken::Integer)) {
4695 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004696 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004697 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
4698 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004699 return MatchOperand_Success;
4700 }
4701
4702 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4703
4704 return MatchOperand_NoMatch;
4705}
4706
David Blaikie960ea3f2014-06-08 16:18:35 +00004707MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004708MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004709 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004710 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004711
4712 auto Token = Parser.getTok();
4713
4714 SMLoc S = Token.getLoc();
4715
4716 if (Token.isNot(AsmToken::Dollar)) {
4717 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4718 if (Token.is(AsmToken::Identifier)) {
4719 if (searchSymbolAlias(Operands))
4720 return MatchOperand_Success;
4721 }
4722 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4723 return MatchOperand_NoMatch;
4724 }
4725 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004726
Toma Tabacu13964452014-09-04 13:23:44 +00004727 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004728 if (ResTy == MatchOperand_Success) {
4729 Parser.Lex(); // $
4730 Parser.Lex(); // identifier
4731 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004732 return ResTy;
4733}
4734
4735MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004736MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004737 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004738 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004739
4740 SMLoc S = getLexer().getLoc();
4741
Daniel Sanderscae9aee2016-08-08 09:33:14 +00004742 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004743 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00004744 if (ResTy != MatchOperand_NoMatch)
4745 return ResTy;
4746
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004747 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00004748 const MCExpr *Expr = nullptr;
4749 if (Parser.parseExpression(Expr)) {
4750 // We have no way of knowing if a symbol was consumed so we must ParseFail
4751 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004752 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004753 Operands.push_back(
4754 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004755 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004756}
4757
Vladimir Medic2b953d02013-10-01 09:48:56 +00004758MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004759MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004760 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004761 const MCExpr *IdVal;
4762 // If the first token is '$' we may have register operand.
4763 if (Parser.getTok().is(AsmToken::Dollar))
4764 return MatchOperand_NoMatch;
4765 SMLoc S = Parser.getTok().getLoc();
4766 if (getParser().parseExpression(IdVal))
4767 return MatchOperand_ParseFail;
4768 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004769 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004770 int64_t Val = MCE->getValue();
4771 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4772 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004773 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004774 return MatchOperand_Success;
4775}
4776
Matheus Almeida779c5932013-11-18 12:32:49 +00004777MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004778MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4779 MCAsmParser &Parser = getParser();
4780 SmallVector<unsigned, 10> Regs;
4781 unsigned RegNo;
4782 unsigned PrevReg = Mips::NoRegister;
4783 bool RegRange = false;
4784 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4785
4786 if (Parser.getTok().isNot(AsmToken::Dollar))
4787 return MatchOperand_ParseFail;
4788
4789 SMLoc S = Parser.getTok().getLoc();
4790 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4791 SMLoc E = getLexer().getLoc();
4792 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4793 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4794 if (RegRange) {
4795 // Remove last register operand because registers from register range
4796 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004797 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4798 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004799 Regs.push_back(RegNo);
4800 } else {
4801 unsigned TmpReg = PrevReg + 1;
4802 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004803 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4804 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4805 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004806 Error(E, "invalid register operand");
4807 return MatchOperand_ParseFail;
4808 }
4809
4810 PrevReg = TmpReg;
4811 Regs.push_back(TmpReg++);
4812 }
4813 }
4814
4815 RegRange = false;
4816 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004817 if ((PrevReg == Mips::NoRegister) &&
4818 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4819 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004820 Error(E, "$16 or $31 expected");
4821 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004822 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4823 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4824 !isGP64bit()) ||
4825 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4826 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4827 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004828 Error(E, "invalid register operand");
4829 return MatchOperand_ParseFail;
4830 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004831 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4832 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4833 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004834 Error(E, "consecutive register numbers expected");
4835 return MatchOperand_ParseFail;
4836 }
4837
4838 Regs.push_back(RegNo);
4839 }
4840
4841 if (Parser.getTok().is(AsmToken::Minus))
4842 RegRange = true;
4843
4844 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4845 !Parser.getTok().isNot(AsmToken::Comma)) {
4846 Error(E, "',' or '-' expected");
4847 return MatchOperand_ParseFail;
4848 }
4849
4850 Lex(); // Consume comma or minus
4851 if (Parser.getTok().isNot(AsmToken::Dollar))
4852 break;
4853
4854 PrevReg = RegNo;
4855 }
4856
4857 SMLoc E = Parser.getTok().getLoc();
4858 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4859 parseMemOperand(Operands);
4860 return MatchOperand_Success;
4861}
4862
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004863MipsAsmParser::OperandMatchResultTy
4864MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4865 MCAsmParser &Parser = getParser();
4866
4867 SMLoc S = Parser.getTok().getLoc();
4868 if (parseAnyRegister(Operands) != MatchOperand_Success)
4869 return MatchOperand_ParseFail;
4870
4871 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00004872 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00004873
Benjamin Kramer2b68d152016-05-09 10:31:17 +00004874 Operands.pop_back();
4875 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004876 return MatchOperand_Success;
4877}
4878
Zoran Jovanovic41688672015-02-10 16:36:20 +00004879MipsAsmParser::OperandMatchResultTy
4880MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4881 MCAsmParser &Parser = getParser();
4882 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4883 SmallVector<unsigned, 10> Regs;
4884
4885 if (Parser.getTok().isNot(AsmToken::Dollar))
4886 return MatchOperand_ParseFail;
4887
4888 SMLoc S = Parser.getTok().getLoc();
4889
4890 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4891 return MatchOperand_ParseFail;
4892
4893 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4894 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4895 Regs.push_back(RegNo);
4896
4897 SMLoc E = Parser.getTok().getLoc();
4898 if (Parser.getTok().isNot(AsmToken::Comma)) {
4899 Error(E, "',' expected");
4900 return MatchOperand_ParseFail;
4901 }
4902
4903 // Remove comma.
4904 Parser.Lex();
4905
4906 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4907 return MatchOperand_ParseFail;
4908
4909 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4910 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4911 Regs.push_back(RegNo);
4912
4913 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4914
4915 return MatchOperand_Success;
4916}
4917
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004918/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4919/// either this.
4920/// ::= '(', register, ')'
4921/// handle it before we iterate so we don't get tripped up by the lack of
4922/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004923bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004924 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004925 if (getLexer().is(AsmToken::LParen)) {
4926 Operands.push_back(
4927 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4928 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004929 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004930 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004931 return Error(Loc, "unexpected token in argument list");
4932 }
4933 if (Parser.getTok().isNot(AsmToken::RParen)) {
4934 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004935 return Error(Loc, "unexpected token, expected ')'");
4936 }
4937 Operands.push_back(
4938 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4939 Parser.Lex();
4940 }
4941 return false;
4942}
4943
4944/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4945/// either one of these.
4946/// ::= '[', register, ']'
4947/// ::= '[', integer, ']'
4948/// handle it before we iterate so we don't get tripped up by the lack of
4949/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004950bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004951 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004952 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004953 if (getLexer().is(AsmToken::LBrac)) {
4954 Operands.push_back(
4955 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4956 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004957 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004958 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004959 return Error(Loc, "unexpected token in argument list");
4960 }
4961 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4962 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004963 return Error(Loc, "unexpected token, expected ']'");
4964 }
4965 Operands.push_back(
4966 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4967 Parser.Lex();
4968 }
4969 return false;
4970}
4971
David Blaikie960ea3f2014-06-08 16:18:35 +00004972bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4973 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004974 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004975 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004976
4977 // We have reached first instruction, module directive are now forbidden.
4978 getTargetStreamer().forbidModuleDirective();
4979
Vladimir Medic74593e62013-07-17 15:00:42 +00004980 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004981 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004982 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004983 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004984 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004985 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004986
4987 // Read the remaining operands.
4988 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4989 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004990 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004991 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004992 return Error(Loc, "unexpected token in argument list");
4993 }
Toma Tabacu13964452014-09-04 13:23:44 +00004994 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004995 return true;
4996 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004997
Jack Carterd0bd6422013-04-18 00:41:53 +00004998 while (getLexer().is(AsmToken::Comma)) {
4999 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00005000 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005001 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005002 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005003 return Error(Loc, "unexpected token in argument list");
5004 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005005 // Parse bracket and parenthesis suffixes before we iterate
5006 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00005007 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005008 return true;
5009 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00005010 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005011 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005012 }
5013 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005014 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5015 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005016 return Error(Loc, "unexpected token in argument list");
5017 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005018 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00005019 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00005020}
5021
Nirav Dave996fc132016-05-05 14:15:46 +00005022// FIXME: Given that these have the same name, these should both be
5023// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005024bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005025 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005026 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00005027}
5028
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005029bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005030 return Error(Loc, ErrorMsg);
5031}
5032
Jack Carter0b744b32012-10-04 02:29:46 +00005033bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005034 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005035 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00005036
5037 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00005038 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00005039
5040 Parser.Lex(); // Eat "noat".
5041
Jack Carterd0bd6422013-04-18 00:41:53 +00005042 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005043 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005044 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005045 return false;
5046 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005047
5048 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005049 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005050 return false;
5051}
Jack Carterd0bd6422013-04-18 00:41:53 +00005052
Jack Carter0b744b32012-10-04 02:29:46 +00005053bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00005054 // Line can be: ".set at", which sets $at to $1
5055 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00005056 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00005057 Parser.Lex(); // Eat "at".
5058
Jack Carter0b744b32012-10-04 02:29:46 +00005059 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005060 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00005061 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00005062
5063 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005064 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005065 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00005066 }
5067
5068 if (getLexer().isNot(AsmToken::Equal)) {
5069 reportParseError("unexpected token, expected equals sign");
5070 return false;
5071 }
5072 Parser.Lex(); // Eat "=".
5073
5074 if (getLexer().isNot(AsmToken::Dollar)) {
5075 if (getLexer().is(AsmToken::EndOfStatement)) {
5076 reportParseError("no register specified");
5077 return false;
5078 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00005079 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00005080 return false;
5081 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005082 }
5083 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00005084
Toma Tabacu16a74492015-02-13 10:30:57 +00005085 // Find out what "reg" is.
5086 unsigned AtRegNo;
5087 const AsmToken &Reg = Parser.getTok();
5088 if (Reg.is(AsmToken::Identifier)) {
5089 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
5090 } else if (Reg.is(AsmToken::Integer)) {
5091 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00005092 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00005093 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00005094 return false;
5095 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005096
5097 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00005098 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005099 reportParseError("invalid register");
5100 return false;
5101 }
5102 Parser.Lex(); // Eat "reg".
5103
5104 // If this is not the end of the statement, report an error.
5105 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5106 reportParseError("unexpected token, expected end of statement");
5107 return false;
5108 }
5109
5110 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
5111
5112 Parser.Lex(); // Consume the EndOfStatement.
5113 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005114}
5115
5116bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005117 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005118 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005119 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005120 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005121 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005122 return false;
5123 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005124 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00005125 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005126 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005127 return false;
5128}
5129
5130bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005131 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005132 Parser.Lex();
5133 // If this is not the end of the statement, report an error.
5134 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005135 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005136 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005137 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005138 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005139 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005140 Parser.Lex(); // Consume the EndOfStatement.
5141 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005142}
5143
5144bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005145 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005146 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005147 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005148 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005149 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005150 return false;
5151 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005152 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005153 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005154 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005155 return false;
5156}
5157
5158bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005159 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005160 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005161 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005162 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005163 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005164 return false;
5165 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005166 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005167 reportParseError("`noreorder' must be set before `nomacro'");
5168 return false;
5169 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005170 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005171 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005172 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005173 return false;
5174}
Jack Carterd76b2372013-03-21 21:44:16 +00005175
Daniel Sanders44934432014-08-07 12:03:36 +00005176bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005177 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005178 Parser.Lex();
5179
5180 // If this is not the end of the statement, report an error.
5181 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005182 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005183
5184 setFeatureBits(Mips::FeatureMSA, "msa");
5185 getTargetStreamer().emitDirectiveSetMsa();
5186 return false;
5187}
5188
5189bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005190 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005191 Parser.Lex();
5192
5193 // If this is not the end of the statement, report an error.
5194 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005195 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005196
5197 clearFeatureBits(Mips::FeatureMSA, "msa");
5198 getTargetStreamer().emitDirectiveSetNoMsa();
5199 return false;
5200}
5201
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005202bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005203 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005204 Parser.Lex(); // Eat "nodsp".
5205
5206 // If this is not the end of the statement, report an error.
5207 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5208 reportParseError("unexpected token, expected end of statement");
5209 return false;
5210 }
5211
5212 clearFeatureBits(Mips::FeatureDSP, "dsp");
5213 getTargetStreamer().emitDirectiveSetNoDsp();
5214 return false;
5215}
5216
Toma Tabacucc2502d2014-11-04 17:18:07 +00005217bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005218 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005219 Parser.Lex(); // Eat "mips16".
5220
Jack Carter39536722014-01-22 23:08:42 +00005221 // If this is not the end of the statement, report an error.
5222 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005223 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005224 return false;
5225 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005226
5227 setFeatureBits(Mips::FeatureMips16, "mips16");
5228 getTargetStreamer().emitDirectiveSetMips16();
5229 Parser.Lex(); // Consume the EndOfStatement.
5230 return false;
5231}
5232
5233bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005234 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005235 Parser.Lex(); // Eat "nomips16".
5236
5237 // If this is not the end of the statement, report an error.
5238 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5239 reportParseError("unexpected token, expected end of statement");
5240 return false;
5241 }
5242
5243 clearFeatureBits(Mips::FeatureMips16, "mips16");
5244 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005245 Parser.Lex(); // Consume the EndOfStatement.
5246 return false;
5247}
5248
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005249bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005250 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005251 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005252 // Line can be: .set fp=32
5253 // .set fp=xx
5254 // .set fp=64
5255 Parser.Lex(); // Eat fp token
5256 AsmToken Tok = Parser.getTok();
5257 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005258 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005259 return false;
5260 }
5261 Parser.Lex(); // Eat '=' token.
5262 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005263
5264 if (!parseFpABIValue(FpAbiVal, ".set"))
5265 return false;
5266
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005267 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005268 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005269 return false;
5270 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005271 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005272 Parser.Lex(); // Consume the EndOfStatement.
5273 return false;
5274}
5275
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005276bool MipsAsmParser::parseSetOddSPRegDirective() {
5277 MCAsmParser &Parser = getParser();
5278
5279 Parser.Lex(); // Eat "oddspreg".
5280 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5281 reportParseError("unexpected token, expected end of statement");
5282 return false;
5283 }
5284
5285 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5286 getTargetStreamer().emitDirectiveSetOddSPReg();
5287 return false;
5288}
5289
5290bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5291 MCAsmParser &Parser = getParser();
5292
5293 Parser.Lex(); // Eat "nooddspreg".
5294 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5295 reportParseError("unexpected token, expected end of statement");
5296 return false;
5297 }
5298
5299 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5300 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5301 return false;
5302}
5303
Toma Tabacu9db22db2014-09-09 10:15:38 +00005304bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005305 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005306 SMLoc Loc = getLexer().getLoc();
5307
5308 Parser.Lex();
5309 if (getLexer().isNot(AsmToken::EndOfStatement))
5310 return reportParseError("unexpected token, expected end of statement");
5311
5312 // Always keep an element on the options "stack" to prevent the user
5313 // from changing the initial options. This is how we remember them.
5314 if (AssemblerOptions.size() == 2)
5315 return reportParseError(Loc, ".set pop with no .set push");
5316
Akira Hatanakab11ef082015-11-14 06:35:56 +00005317 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005318 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005319 setAvailableFeatures(
5320 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5321 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005322
5323 getTargetStreamer().emitDirectiveSetPop();
5324 return false;
5325}
5326
5327bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005328 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005329 Parser.Lex();
5330 if (getLexer().isNot(AsmToken::EndOfStatement))
5331 return reportParseError("unexpected token, expected end of statement");
5332
5333 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005334 AssemblerOptions.push_back(
5335 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005336
5337 getTargetStreamer().emitDirectiveSetPush();
5338 return false;
5339}
5340
Toma Tabacu29696502015-06-02 09:48:04 +00005341bool MipsAsmParser::parseSetSoftFloatDirective() {
5342 MCAsmParser &Parser = getParser();
5343 Parser.Lex();
5344 if (getLexer().isNot(AsmToken::EndOfStatement))
5345 return reportParseError("unexpected token, expected end of statement");
5346
5347 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5348 getTargetStreamer().emitDirectiveSetSoftFloat();
5349 return false;
5350}
5351
5352bool MipsAsmParser::parseSetHardFloatDirective() {
5353 MCAsmParser &Parser = getParser();
5354 Parser.Lex();
5355 if (getLexer().isNot(AsmToken::EndOfStatement))
5356 return reportParseError("unexpected token, expected end of statement");
5357
5358 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5359 getTargetStreamer().emitDirectiveSetHardFloat();
5360 return false;
5361}
5362
Jack Carterd76b2372013-03-21 21:44:16 +00005363bool MipsAsmParser::parseSetAssignment() {
5364 StringRef Name;
5365 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005366 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005367
5368 if (Parser.parseIdentifier(Name))
5369 reportParseError("expected identifier after .set");
5370
5371 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005372 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005373 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005374
Jack Carter3b2c96e2014-01-22 23:31:38 +00005375 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005376 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005377
Jim Grosbach6f482002015-05-18 18:43:14 +00005378 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005379 Sym->setVariableValue(Value);
5380
5381 return false;
5382}
Jack Carterd0bd6422013-04-18 00:41:53 +00005383
Toma Tabacu26647792014-09-09 12:52:14 +00005384bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005385 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005386 Parser.Lex();
5387 if (getLexer().isNot(AsmToken::EndOfStatement))
5388 return reportParseError("unexpected token, expected end of statement");
5389
5390 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005391 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005392 setAvailableFeatures(
5393 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5394 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005395 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5396
5397 getTargetStreamer().emitDirectiveSetMips0();
5398 return false;
5399}
5400
Toma Tabacu85618b32014-08-19 14:22:52 +00005401bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005402 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005403 Parser.Lex();
5404 if (getLexer().isNot(AsmToken::Equal))
5405 return reportParseError("unexpected token, expected equals sign");
5406
5407 Parser.Lex();
5408 StringRef Arch;
5409 if (Parser.parseIdentifier(Arch))
5410 return reportParseError("expected arch identifier");
5411
5412 StringRef ArchFeatureName =
5413 StringSwitch<StringRef>(Arch)
5414 .Case("mips1", "mips1")
5415 .Case("mips2", "mips2")
5416 .Case("mips3", "mips3")
5417 .Case("mips4", "mips4")
5418 .Case("mips5", "mips5")
5419 .Case("mips32", "mips32")
5420 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005421 .Case("mips32r3", "mips32r3")
5422 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005423 .Case("mips32r6", "mips32r6")
5424 .Case("mips64", "mips64")
5425 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005426 .Case("mips64r3", "mips64r3")
5427 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005428 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005429 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005430 .Case("r4000", "mips3") // This is an implementation of Mips3.
5431 .Default("");
5432
5433 if (ArchFeatureName.empty())
5434 return reportParseError("unsupported architecture");
5435
5436 selectArch(ArchFeatureName);
5437 getTargetStreamer().emitDirectiveSetArch(Arch);
5438 return false;
5439}
5440
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005441bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005442 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005443 Parser.Lex();
5444 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005445 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005446
Matheus Almeida2852af82014-04-22 10:15:54 +00005447 switch (Feature) {
5448 default:
5449 llvm_unreachable("Unimplemented feature");
5450 case Mips::FeatureDSP:
5451 setFeatureBits(Mips::FeatureDSP, "dsp");
5452 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005453 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005454 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00005455 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00005456 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005457 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005458 case Mips::FeatureMips1:
5459 selectArch("mips1");
5460 getTargetStreamer().emitDirectiveSetMips1();
5461 break;
5462 case Mips::FeatureMips2:
5463 selectArch("mips2");
5464 getTargetStreamer().emitDirectiveSetMips2();
5465 break;
5466 case Mips::FeatureMips3:
5467 selectArch("mips3");
5468 getTargetStreamer().emitDirectiveSetMips3();
5469 break;
5470 case Mips::FeatureMips4:
5471 selectArch("mips4");
5472 getTargetStreamer().emitDirectiveSetMips4();
5473 break;
5474 case Mips::FeatureMips5:
5475 selectArch("mips5");
5476 getTargetStreamer().emitDirectiveSetMips5();
5477 break;
5478 case Mips::FeatureMips32:
5479 selectArch("mips32");
5480 getTargetStreamer().emitDirectiveSetMips32();
5481 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005482 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005483 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005484 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005485 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005486 case Mips::FeatureMips32r3:
5487 selectArch("mips32r3");
5488 getTargetStreamer().emitDirectiveSetMips32R3();
5489 break;
5490 case Mips::FeatureMips32r5:
5491 selectArch("mips32r5");
5492 getTargetStreamer().emitDirectiveSetMips32R5();
5493 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005494 case Mips::FeatureMips32r6:
5495 selectArch("mips32r6");
5496 getTargetStreamer().emitDirectiveSetMips32R6();
5497 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005498 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005499 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005500 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005501 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005502 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005503 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005504 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005505 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005506 case Mips::FeatureMips64r3:
5507 selectArch("mips64r3");
5508 getTargetStreamer().emitDirectiveSetMips64R3();
5509 break;
5510 case Mips::FeatureMips64r5:
5511 selectArch("mips64r5");
5512 getTargetStreamer().emitDirectiveSetMips64R5();
5513 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005514 case Mips::FeatureMips64r6:
5515 selectArch("mips64r6");
5516 getTargetStreamer().emitDirectiveSetMips64R6();
5517 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005518 }
5519 return false;
5520}
5521
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005522bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005523 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005524 if (getLexer().isNot(AsmToken::Comma)) {
5525 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005526 return Error(Loc, ErrorStr);
5527 }
5528
Matheus Almeida2852af82014-04-22 10:15:54 +00005529 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005530 return true;
5531}
5532
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005533// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5534// In this class, it is only used for .cprestore.
5535// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5536// MipsTargetELFStreamer and MipsAsmParser.
5537bool MipsAsmParser::isPicAndNotNxxAbi() {
5538 return inPicMode() && !(isABI_N32() || isABI_N64());
5539}
5540
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005541bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005542 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005543 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005544
Toma Tabacudde4c462014-11-06 10:02:45 +00005545 if (inMips16Mode()) {
5546 reportParseError(".cpload is not supported in Mips16 mode");
5547 return false;
5548 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005549
David Blaikie960ea3f2014-06-08 16:18:35 +00005550 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005551 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005552 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5553 reportParseError("expected register containing function address");
5554 return false;
5555 }
5556
David Blaikie960ea3f2014-06-08 16:18:35 +00005557 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5558 if (!RegOpnd.isGPRAsmReg()) {
5559 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005560 return false;
5561 }
5562
Toma Tabacudde4c462014-11-06 10:02:45 +00005563 // If this is not the end of the statement, report an error.
5564 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5565 reportParseError("unexpected token, expected end of statement");
5566 return false;
5567 }
5568
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005569 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005570 return false;
5571}
5572
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005573bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5574 MCAsmParser &Parser = getParser();
5575
5576 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5577 // is used in non-PIC mode.
5578
5579 if (inMips16Mode()) {
5580 reportParseError(".cprestore is not supported in Mips16 mode");
5581 return false;
5582 }
5583
5584 // Get the stack offset value.
5585 const MCExpr *StackOffset;
5586 int64_t StackOffsetVal;
5587 if (Parser.parseExpression(StackOffset)) {
5588 reportParseError("expected stack offset value");
5589 return false;
5590 }
5591
5592 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5593 reportParseError("stack offset is not an absolute expression");
5594 return false;
5595 }
5596
5597 if (StackOffsetVal < 0) {
5598 Warning(Loc, ".cprestore with negative stack offset has no effect");
5599 IsCpRestoreSet = false;
5600 } else {
5601 IsCpRestoreSet = true;
5602 CpRestoreOffset = StackOffsetVal;
5603 }
5604
5605 // If this is not the end of the statement, report an error.
5606 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5607 reportParseError("unexpected token, expected end of statement");
5608 return false;
5609 }
5610
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005611 if (!getTargetStreamer().emitDirectiveCpRestore(
5612 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005613 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005614 Parser.Lex(); // Consume the EndOfStatement.
5615 return false;
5616}
5617
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005618bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005619 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005620 unsigned FuncReg;
5621 unsigned Save;
5622 bool SaveIsReg = true;
5623
Matheus Almeida7e815762014-06-18 13:08:59 +00005624 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005625 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005626 if (ResTy == MatchOperand_NoMatch) {
5627 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005628 return false;
5629 }
5630
5631 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5632 if (!FuncRegOpnd.isGPRAsmReg()) {
5633 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005634 return false;
5635 }
5636
5637 FuncReg = FuncRegOpnd.getGPR32Reg();
5638 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005639
Toma Tabacu65f10572014-09-16 15:00:52 +00005640 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005641 return true;
5642
Toma Tabacu13964452014-09-04 13:23:44 +00005643 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005644 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005645 const MCExpr *OffsetExpr;
5646 int64_t OffsetVal;
5647 SMLoc ExprLoc = getLexer().getLoc();
5648
5649 if (Parser.parseExpression(OffsetExpr) ||
5650 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5651 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005652 return false;
5653 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005654
5655 Save = OffsetVal;
5656 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005657 } else {
5658 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5659 if (!SaveOpnd.isGPRAsmReg()) {
5660 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005661 return false;
5662 }
5663 Save = SaveOpnd.getGPR32Reg();
5664 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005665
Toma Tabacu65f10572014-09-16 15:00:52 +00005666 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005667 return true;
5668
Toma Tabacu8874eac2015-02-18 13:46:53 +00005669 const MCExpr *Expr;
5670 if (Parser.parseExpression(Expr)) {
5671 reportParseError("expected expression");
5672 return false;
5673 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005674
Toma Tabacu8874eac2015-02-18 13:46:53 +00005675 if (Expr->getKind() != MCExpr::SymbolRef) {
5676 reportParseError("expected symbol");
5677 return false;
5678 }
5679 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5680
Daniel Sandersf173dda2015-09-22 10:50:09 +00005681 CpSaveLocation = Save;
5682 CpSaveLocationIsRegister = SaveIsReg;
5683
Toma Tabacu8874eac2015-02-18 13:46:53 +00005684 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5685 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005686 return false;
5687}
5688
Daniel Sandersf173dda2015-09-22 10:50:09 +00005689bool MipsAsmParser::parseDirectiveCPReturn() {
5690 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5691 CpSaveLocationIsRegister);
5692 return false;
5693}
5694
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005695bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005696 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005697 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5698 const AsmToken &Tok = Parser.getTok();
5699
5700 if (Tok.getString() == "2008") {
5701 Parser.Lex();
5702 getTargetStreamer().emitDirectiveNaN2008();
5703 return false;
5704 } else if (Tok.getString() == "legacy") {
5705 Parser.Lex();
5706 getTargetStreamer().emitDirectiveNaNLegacy();
5707 return false;
5708 }
5709 }
5710 // If we don't recognize the option passed to the .nan
5711 // directive (e.g. no option or unknown option), emit an error.
5712 reportParseError("invalid option in .nan directive");
5713 return false;
5714}
5715
Jack Carter0b744b32012-10-04 02:29:46 +00005716bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005717 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005718 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005719 const AsmToken &Tok = Parser.getTok();
5720
5721 if (Tok.getString() == "noat") {
5722 return parseSetNoAtDirective();
5723 } else if (Tok.getString() == "at") {
5724 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005725 } else if (Tok.getString() == "arch") {
5726 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005727 } else if (Tok.getString() == "fp") {
5728 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005729 } else if (Tok.getString() == "oddspreg") {
5730 return parseSetOddSPRegDirective();
5731 } else if (Tok.getString() == "nooddspreg") {
5732 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005733 } else if (Tok.getString() == "pop") {
5734 return parseSetPopDirective();
5735 } else if (Tok.getString() == "push") {
5736 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005737 } else if (Tok.getString() == "reorder") {
5738 return parseSetReorderDirective();
5739 } else if (Tok.getString() == "noreorder") {
5740 return parseSetNoReorderDirective();
5741 } else if (Tok.getString() == "macro") {
5742 return parseSetMacroDirective();
5743 } else if (Tok.getString() == "nomacro") {
5744 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005745 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005746 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005747 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005748 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005749 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00005750 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005751 getTargetStreamer().emitDirectiveSetNoMicroMips();
5752 Parser.eatToEndOfStatement();
5753 return false;
5754 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005755 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005756 } else if (Tok.getString() == "mips0") {
5757 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005758 } else if (Tok.getString() == "mips1") {
5759 return parseSetFeature(Mips::FeatureMips1);
5760 } else if (Tok.getString() == "mips2") {
5761 return parseSetFeature(Mips::FeatureMips2);
5762 } else if (Tok.getString() == "mips3") {
5763 return parseSetFeature(Mips::FeatureMips3);
5764 } else if (Tok.getString() == "mips4") {
5765 return parseSetFeature(Mips::FeatureMips4);
5766 } else if (Tok.getString() == "mips5") {
5767 return parseSetFeature(Mips::FeatureMips5);
5768 } else if (Tok.getString() == "mips32") {
5769 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005770 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005771 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005772 } else if (Tok.getString() == "mips32r3") {
5773 return parseSetFeature(Mips::FeatureMips32r3);
5774 } else if (Tok.getString() == "mips32r5") {
5775 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005776 } else if (Tok.getString() == "mips32r6") {
5777 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005778 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005779 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005780 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005781 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005782 } else if (Tok.getString() == "mips64r3") {
5783 return parseSetFeature(Mips::FeatureMips64r3);
5784 } else if (Tok.getString() == "mips64r5") {
5785 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005786 } else if (Tok.getString() == "mips64r6") {
5787 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005788 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005789 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005790 } else if (Tok.getString() == "nodsp") {
5791 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005792 } else if (Tok.getString() == "msa") {
5793 return parseSetMsaDirective();
5794 } else if (Tok.getString() == "nomsa") {
5795 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005796 } else if (Tok.getString() == "softfloat") {
5797 return parseSetSoftFloatDirective();
5798 } else if (Tok.getString() == "hardfloat") {
5799 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005800 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005801 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005802 parseSetAssignment();
5803 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005804 }
Jack Carter07c818d2013-01-25 01:31:34 +00005805
Jack Carter0b744b32012-10-04 02:29:46 +00005806 return true;
5807}
5808
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005809/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005810/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005811bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005812 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005813 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5814 for (;;) {
5815 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005816 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005817 return true;
5818
5819 getParser().getStreamer().EmitValue(Value, Size);
5820
5821 if (getLexer().is(AsmToken::EndOfStatement))
5822 break;
5823
Jack Carter07c818d2013-01-25 01:31:34 +00005824 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005825 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005826 Parser.Lex();
5827 }
5828 }
5829
5830 Parser.Lex();
5831 return false;
5832}
5833
Vladimir Medic4c299852013-11-06 11:27:05 +00005834/// parseDirectiveGpWord
5835/// ::= .gpword local_sym
5836bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005837 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005838 const MCExpr *Value;
5839 // EmitGPRel32Value requires an expression, so we are using base class
5840 // method to evaluate the expression.
5841 if (getParser().parseExpression(Value))
5842 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005843 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005844
Vladimir Medice10c1122013-11-13 13:18:04 +00005845 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005846 return Error(getLexer().getLoc(),
5847 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005848 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005849 return false;
5850}
5851
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005852/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005853/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005854bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005855 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005856 const MCExpr *Value;
5857 // EmitGPRel64Value requires an expression, so we are using base class
5858 // method to evaluate the expression.
5859 if (getParser().parseExpression(Value))
5860 return true;
5861 getParser().getStreamer().EmitGPRel64Value(Value);
5862
5863 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00005864 return Error(getLexer().getLoc(),
5865 "unexpected token, expected end of statement");
5866 Parser.Lex(); // Eat EndOfStatement token.
5867 return false;
5868}
5869
5870/// parseDirectiveDtpRelWord
5871/// ::= .dtprelword tls_sym
5872bool MipsAsmParser::parseDirectiveDtpRelWord() {
5873 MCAsmParser &Parser = getParser();
5874 const MCExpr *Value;
5875 // EmitDTPRel32Value requires an expression, so we are using base class
5876 // method to evaluate the expression.
5877 if (getParser().parseExpression(Value))
5878 return true;
5879 getParser().getStreamer().EmitDTPRel32Value(Value);
5880
5881 if (getLexer().isNot(AsmToken::EndOfStatement))
5882 return Error(getLexer().getLoc(),
5883 "unexpected token, expected end of statement");
5884 Parser.Lex(); // Eat EndOfStatement token.
5885 return false;
5886}
5887
5888/// parseDirectiveDtpRelDWord
5889/// ::= .dtpreldword tls_sym
5890bool MipsAsmParser::parseDirectiveDtpRelDWord() {
5891 MCAsmParser &Parser = getParser();
5892 const MCExpr *Value;
5893 // EmitDTPRel64Value requires an expression, so we are using base class
5894 // method to evaluate the expression.
5895 if (getParser().parseExpression(Value))
5896 return true;
5897 getParser().getStreamer().EmitDTPRel64Value(Value);
5898
5899 if (getLexer().isNot(AsmToken::EndOfStatement))
5900 return Error(getLexer().getLoc(),
5901 "unexpected token, expected end of statement");
5902 Parser.Lex(); // Eat EndOfStatement token.
5903 return false;
5904}
5905
5906/// parseDirectiveTpRelWord
5907/// ::= .tprelword tls_sym
5908bool MipsAsmParser::parseDirectiveTpRelWord() {
5909 MCAsmParser &Parser = getParser();
5910 const MCExpr *Value;
5911 // EmitTPRel32Value requires an expression, so we are using base class
5912 // method to evaluate the expression.
5913 if (getParser().parseExpression(Value))
5914 return true;
5915 getParser().getStreamer().EmitTPRel32Value(Value);
5916
5917 if (getLexer().isNot(AsmToken::EndOfStatement))
5918 return Error(getLexer().getLoc(),
5919 "unexpected token, expected end of statement");
5920 Parser.Lex(); // Eat EndOfStatement token.
5921 return false;
5922}
5923
5924/// parseDirectiveTpRelDWord
5925/// ::= .tpreldword tls_sym
5926bool MipsAsmParser::parseDirectiveTpRelDWord() {
5927 MCAsmParser &Parser = getParser();
5928 const MCExpr *Value;
5929 // EmitTPRel64Value requires an expression, so we are using base class
5930 // method to evaluate the expression.
5931 if (getParser().parseExpression(Value))
5932 return true;
5933 getParser().getStreamer().EmitTPRel64Value(Value);
5934
5935 if (getLexer().isNot(AsmToken::EndOfStatement))
5936 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005937 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005938 Parser.Lex(); // Eat EndOfStatement token.
5939 return false;
5940}
5941
Jack Carter0cd3c192014-01-06 23:27:31 +00005942bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005943 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005944 // Get the option token.
5945 AsmToken Tok = Parser.getTok();
5946 // At the moment only identifiers are supported.
5947 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00005948 return Error(Parser.getTok().getLoc(),
5949 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005950 }
5951
5952 StringRef Option = Tok.getIdentifier();
5953
5954 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005955 // MipsAsmParser needs to know if the current PIC mode changes.
5956 IsPicEnabled = false;
5957
Jack Carter0cd3c192014-01-06 23:27:31 +00005958 getTargetStreamer().emitDirectiveOptionPic0();
5959 Parser.Lex();
5960 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00005961 return Error(Parser.getTok().getLoc(),
5962 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005963 }
5964 return false;
5965 }
5966
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005967 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005968 // MipsAsmParser needs to know if the current PIC mode changes.
5969 IsPicEnabled = true;
5970
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005971 getTargetStreamer().emitDirectiveOptionPic2();
5972 Parser.Lex();
5973 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00005974 return Error(Parser.getTok().getLoc(),
5975 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005976 }
5977 return false;
5978 }
5979
Jack Carter0cd3c192014-01-06 23:27:31 +00005980 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005981 Warning(Parser.getTok().getLoc(),
5982 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005983 Parser.eatToEndOfStatement();
5984 return false;
5985}
5986
Toma Tabacu9ca50962015-04-16 09:53:47 +00005987/// parseInsnDirective
5988/// ::= .insn
5989bool MipsAsmParser::parseInsnDirective() {
5990 // If this is not the end of the statement, report an error.
5991 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5992 reportParseError("unexpected token, expected end of statement");
5993 return false;
5994 }
5995
5996 // The actual label marking happens in
5997 // MipsELFStreamer::createPendingLabelRelocs().
5998 getTargetStreamer().emitDirectiveInsn();
5999
6000 getParser().Lex(); // Eat EndOfStatement token.
6001 return false;
6002}
6003
Simon Atanasyanbe186202016-02-11 06:45:54 +00006004/// parseSSectionDirective
6005/// ::= .sbss
6006/// ::= .sdata
6007bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
6008 // If this is not the end of the statement, report an error.
6009 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6010 reportParseError("unexpected token, expected end of statement");
6011 return false;
6012 }
6013
6014 MCSection *ELFSection = getContext().getELFSection(
6015 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
6016 getParser().getStreamer().SwitchSection(ELFSection);
6017
6018 getParser().Lex(); // Eat EndOfStatement token.
6019 return false;
6020}
6021
Daniel Sanders7e527422014-07-10 13:38:23 +00006022/// parseDirectiveModule
6023/// ::= .module oddspreg
6024/// ::= .module nooddspreg
6025/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00006026/// ::= .module softfloat
6027/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006028bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006029 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006030 MCAsmLexer &Lexer = getLexer();
6031 SMLoc L = Lexer.getLoc();
6032
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006033 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006034 // TODO : get a better message.
6035 reportParseError(".module directive must appear before any code");
6036 return false;
6037 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006038
Toma Tabacuc405c822015-01-23 10:40:19 +00006039 StringRef Option;
6040 if (Parser.parseIdentifier(Option)) {
6041 reportParseError("expected .module option identifier");
6042 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006043 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006044
Toma Tabacuc405c822015-01-23 10:40:19 +00006045 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006046 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006047
Toma Tabacu3c499582015-06-25 10:56:57 +00006048 // Synchronize the abiflags information with the FeatureBits information we
6049 // changed above.
6050 getTargetStreamer().updateABIInfo(*this);
6051
6052 // If printing assembly, use the recently updated abiflags information.
6053 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6054 // emitted at the end).
6055 getTargetStreamer().emitDirectiveModuleOddSPReg();
6056
Toma Tabacuc405c822015-01-23 10:40:19 +00006057 // If this is not the end of the statement, report an error.
6058 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6059 reportParseError("unexpected token, expected end of statement");
6060 return false;
6061 }
6062
6063 return false; // parseDirectiveModule has finished successfully.
6064 } else if (Option == "nooddspreg") {
6065 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006066 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00006067 }
6068
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006069 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006070
Toma Tabacu3c499582015-06-25 10:56:57 +00006071 // Synchronize the abiflags information with the FeatureBits information we
6072 // changed above.
6073 getTargetStreamer().updateABIInfo(*this);
6074
6075 // If printing assembly, use the recently updated abiflags information.
6076 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6077 // emitted at the end).
6078 getTargetStreamer().emitDirectiveModuleOddSPReg();
6079
Toma Tabacuc405c822015-01-23 10:40:19 +00006080 // If this is not the end of the statement, report an error.
6081 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6082 reportParseError("unexpected token, expected end of statement");
6083 return false;
6084 }
6085
6086 return false; // parseDirectiveModule has finished successfully.
6087 } else if (Option == "fp") {
6088 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00006089 } else if (Option == "softfloat") {
6090 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6091
6092 // Synchronize the ABI Flags information with the FeatureBits information we
6093 // updated above.
6094 getTargetStreamer().updateABIInfo(*this);
6095
6096 // If printing assembly, use the recently updated ABI Flags information.
6097 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6098 // emitted later).
6099 getTargetStreamer().emitDirectiveModuleSoftFloat();
6100
6101 // If this is not the end of the statement, report an error.
6102 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6103 reportParseError("unexpected token, expected end of statement");
6104 return false;
6105 }
6106
6107 return false; // parseDirectiveModule has finished successfully.
6108 } else if (Option == "hardfloat") {
6109 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6110
6111 // Synchronize the ABI Flags information with the FeatureBits information we
6112 // updated above.
6113 getTargetStreamer().updateABIInfo(*this);
6114
6115 // If printing assembly, use the recently updated ABI Flags information.
6116 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6117 // emitted later).
6118 getTargetStreamer().emitDirectiveModuleHardFloat();
6119
6120 // If this is not the end of the statement, report an error.
6121 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6122 reportParseError("unexpected token, expected end of statement");
6123 return false;
6124 }
6125
6126 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00006127 } else {
6128 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
6129 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006130}
6131
6132/// parseDirectiveModuleFP
6133/// ::= =32
6134/// ::= =xx
6135/// ::= =64
6136bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006137 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006138 MCAsmLexer &Lexer = getLexer();
6139
6140 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006141 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006142 return false;
6143 }
6144 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006145
Daniel Sanders7e527422014-07-10 13:38:23 +00006146 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006147 if (!parseFpABIValue(FpABI, ".module"))
6148 return false;
6149
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006150 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006151 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006152 return false;
6153 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006154
Toma Tabacua64e5402015-06-25 12:44:38 +00006155 // Synchronize the abiflags information with the FeatureBits information we
6156 // changed above.
6157 getTargetStreamer().updateABIInfo(*this);
6158
6159 // If printing assembly, use the recently updated abiflags information.
6160 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6161 // emitted at the end).
6162 getTargetStreamer().emitDirectiveModuleFP();
6163
Daniel Sanders7e527422014-07-10 13:38:23 +00006164 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006165 return false;
6166}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006167
Daniel Sanders7e527422014-07-10 13:38:23 +00006168bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006169 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006170 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006171 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006172 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006173
6174 if (Lexer.is(AsmToken::Identifier)) {
6175 StringRef Value = Parser.getTok().getString();
6176 Parser.Lex();
6177
6178 if (Value != "xx") {
6179 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6180 return false;
6181 }
6182
6183 if (!isABI_O32()) {
6184 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
6185 return false;
6186 }
6187
Daniel Sanders7e527422014-07-10 13:38:23 +00006188 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006189 if (ModuleLevelOptions) {
6190 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6191 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6192 } else {
6193 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6194 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6195 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006196 return true;
6197 }
6198
6199 if (Lexer.is(AsmToken::Integer)) {
6200 unsigned Value = Parser.getTok().getIntVal();
6201 Parser.Lex();
6202
6203 if (Value != 32 && Value != 64) {
6204 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6205 return false;
6206 }
6207
6208 if (Value == 32) {
6209 if (!isABI_O32()) {
6210 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6211 return false;
6212 }
6213
Daniel Sanders7e527422014-07-10 13:38:23 +00006214 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006215 if (ModuleLevelOptions) {
6216 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6217 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6218 } else {
6219 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6220 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6221 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006222 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006223 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006224 if (ModuleLevelOptions) {
6225 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6226 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6227 } else {
6228 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6229 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6230 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006231 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006232
Daniel Sanders7e527422014-07-10 13:38:23 +00006233 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006234 }
6235
6236 return false;
6237}
6238
Jack Carter0b744b32012-10-04 02:29:46 +00006239bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006240 // This returns false if this function recognizes the directive
6241 // regardless of whether it is successfully handles or reports an
6242 // error. Otherwise it returns true to give the generic parser a
6243 // chance at recognizing it.
6244
Rafael Espindola961d4692014-11-11 05:18:41 +00006245 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006246 StringRef IDVal = DirectiveID.getString();
6247
Nirav Dave996fc132016-05-05 14:15:46 +00006248 if (IDVal == ".cpload") {
6249 parseDirectiveCpLoad(DirectiveID.getLoc());
6250 return false;
6251 }
6252 if (IDVal == ".cprestore") {
6253 parseDirectiveCpRestore(DirectiveID.getLoc());
6254 return false;
6255 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006256 if (IDVal == ".dword") {
6257 parseDataDirective(8, DirectiveID.getLoc());
6258 return false;
6259 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006260 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006261 StringRef SymbolName;
6262
6263 if (Parser.parseIdentifier(SymbolName)) {
6264 reportParseError("expected identifier after .ent");
6265 return false;
6266 }
6267
6268 // There's an undocumented extension that allows an integer to
6269 // follow the name of the procedure which AFAICS is ignored by GAS.
6270 // Example: .ent foo,2
6271 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6272 if (getLexer().isNot(AsmToken::Comma)) {
6273 // Even though we accept this undocumented extension for compatibility
6274 // reasons, the additional integer argument does not actually change
6275 // the behaviour of the '.ent' directive, so we would like to discourage
6276 // its use. We do this by not referring to the extended version in
6277 // error messages which are not directly related to its use.
6278 reportParseError("unexpected token, expected end of statement");
6279 return false;
6280 }
6281 Parser.Lex(); // Eat the comma.
6282 const MCExpr *DummyNumber;
6283 int64_t DummyNumberVal;
6284 // If the user was explicitly trying to use the extended version,
6285 // we still give helpful extension-related error messages.
6286 if (Parser.parseExpression(DummyNumber)) {
6287 reportParseError("expected number after comma");
6288 return false;
6289 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006290 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006291 reportParseError("expected an absolute expression after comma");
6292 return false;
6293 }
6294 }
6295
6296 // If this is not the end of the statement, report an error.
6297 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6298 reportParseError("unexpected token, expected end of statement");
6299 return false;
6300 }
6301
Jim Grosbach6f482002015-05-18 18:43:14 +00006302 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006303
6304 getTargetStreamer().emitDirectiveEnt(*Sym);
6305 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006306 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006307 return false;
6308 }
6309
Jack Carter07c818d2013-01-25 01:31:34 +00006310 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006311 StringRef SymbolName;
6312
6313 if (Parser.parseIdentifier(SymbolName)) {
6314 reportParseError("expected identifier after .end");
6315 return false;
6316 }
6317
6318 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6319 reportParseError("unexpected token, expected end of statement");
6320 return false;
6321 }
6322
6323 if (CurrentFn == nullptr) {
6324 reportParseError(".end used without .ent");
6325 return false;
6326 }
6327
6328 if ((SymbolName != CurrentFn->getName())) {
6329 reportParseError(".end symbol does not match .ent symbol");
6330 return false;
6331 }
6332
6333 getTargetStreamer().emitDirectiveEnd(SymbolName);
6334 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006335 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006336 return false;
6337 }
6338
Jack Carter07c818d2013-01-25 01:31:34 +00006339 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006340 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6341 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006342 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006343 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6344 reportParseError("expected stack register");
6345 return false;
6346 }
6347
6348 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6349 if (!StackRegOpnd.isGPRAsmReg()) {
6350 reportParseError(StackRegOpnd.getStartLoc(),
6351 "expected general purpose register");
6352 return false;
6353 }
6354 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6355
6356 if (Parser.getTok().is(AsmToken::Comma))
6357 Parser.Lex();
6358 else {
6359 reportParseError("unexpected token, expected comma");
6360 return false;
6361 }
6362
6363 // Parse the frame size.
6364 const MCExpr *FrameSize;
6365 int64_t FrameSizeVal;
6366
6367 if (Parser.parseExpression(FrameSize)) {
6368 reportParseError("expected frame size value");
6369 return false;
6370 }
6371
Jim Grosbach13760bd2015-05-30 01:25:56 +00006372 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006373 reportParseError("frame size not an absolute expression");
6374 return false;
6375 }
6376
6377 if (Parser.getTok().is(AsmToken::Comma))
6378 Parser.Lex();
6379 else {
6380 reportParseError("unexpected token, expected comma");
6381 return false;
6382 }
6383
6384 // Parse the return register.
6385 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006386 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006387 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6388 reportParseError("expected return register");
6389 return false;
6390 }
6391
6392 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6393 if (!ReturnRegOpnd.isGPRAsmReg()) {
6394 reportParseError(ReturnRegOpnd.getStartLoc(),
6395 "expected general purpose register");
6396 return false;
6397 }
6398
6399 // If this is not the end of the statement, report an error.
6400 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6401 reportParseError("unexpected token, expected end of statement");
6402 return false;
6403 }
6404
6405 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6406 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006407 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006408 return false;
6409 }
6410
Jack Carter07c818d2013-01-25 01:31:34 +00006411 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006412 parseDirectiveSet();
6413 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006414 }
6415
Daniel Sandersd97a6342014-08-13 10:07:34 +00006416 if (IDVal == ".mask" || IDVal == ".fmask") {
6417 // .mask bitmask, frame_offset
6418 // bitmask: One bit for each register used.
6419 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6420 // first register is expected to be saved.
6421 // Examples:
6422 // .mask 0x80000000, -4
6423 // .fmask 0x80000000, -4
6424 //
Jack Carterbe332172012-09-07 00:48:02 +00006425
Daniel Sandersd97a6342014-08-13 10:07:34 +00006426 // Parse the bitmask
6427 const MCExpr *BitMask;
6428 int64_t BitMaskVal;
6429
6430 if (Parser.parseExpression(BitMask)) {
6431 reportParseError("expected bitmask value");
6432 return false;
6433 }
6434
Jim Grosbach13760bd2015-05-30 01:25:56 +00006435 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006436 reportParseError("bitmask not an absolute expression");
6437 return false;
6438 }
6439
6440 if (Parser.getTok().is(AsmToken::Comma))
6441 Parser.Lex();
6442 else {
6443 reportParseError("unexpected token, expected comma");
6444 return false;
6445 }
6446
6447 // Parse the frame_offset
6448 const MCExpr *FrameOffset;
6449 int64_t FrameOffsetVal;
6450
6451 if (Parser.parseExpression(FrameOffset)) {
6452 reportParseError("expected frame offset value");
6453 return false;
6454 }
6455
Jim Grosbach13760bd2015-05-30 01:25:56 +00006456 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006457 reportParseError("frame offset not an absolute expression");
6458 return false;
6459 }
6460
6461 // If this is not the end of the statement, report an error.
6462 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6463 reportParseError("unexpected token, expected end of statement");
6464 return false;
6465 }
6466
6467 if (IDVal == ".mask")
6468 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6469 else
6470 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006471 return false;
6472 }
6473
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006474 if (IDVal == ".nan")
6475 return parseDirectiveNaN();
6476
Jack Carter07c818d2013-01-25 01:31:34 +00006477 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006478 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006479 return false;
6480 }
6481
Rafael Espindolab59fb732014-03-28 18:50:26 +00006482 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006483 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006484 return false;
6485 }
6486
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006487 if (IDVal == ".dtprelword") {
6488 parseDirectiveDtpRelWord();
6489 return false;
6490 }
6491
6492 if (IDVal == ".dtpreldword") {
6493 parseDirectiveDtpRelDWord();
6494 return false;
6495 }
6496
6497 if (IDVal == ".tprelword") {
6498 parseDirectiveTpRelWord();
6499 return false;
6500 }
6501
6502 if (IDVal == ".tpreldword") {
6503 parseDirectiveTpRelDWord();
6504 return false;
6505 }
6506
Jack Carter07c818d2013-01-25 01:31:34 +00006507 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006508 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006509 return false;
6510 }
6511
Scott Egertond1aeb052016-02-15 16:11:51 +00006512 if (IDVal == ".hword") {
6513 parseDataDirective(2, DirectiveID.getLoc());
6514 return false;
6515 }
6516
Nirav Dave996fc132016-05-05 14:15:46 +00006517 if (IDVal == ".option") {
6518 parseDirectiveOption();
6519 return false;
6520 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006521
6522 if (IDVal == ".abicalls") {
6523 getTargetStreamer().emitDirectiveAbiCalls();
6524 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006525 Error(Parser.getTok().getLoc(),
6526 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006527 }
6528 return false;
6529 }
6530
Nirav Dave996fc132016-05-05 14:15:46 +00006531 if (IDVal == ".cpsetup") {
6532 parseDirectiveCPSetup();
6533 return false;
6534 }
6535 if (IDVal == ".cpreturn") {
6536 parseDirectiveCPReturn();
6537 return false;
6538 }
6539 if (IDVal == ".module") {
6540 parseDirectiveModule();
6541 return false;
6542 }
6543 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6544 parseInternalDirectiveReallowModule();
6545 return false;
6546 }
6547 if (IDVal == ".insn") {
6548 parseInsnDirective();
6549 return false;
6550 }
6551 if (IDVal == ".sbss") {
6552 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6553 return false;
6554 }
6555 if (IDVal == ".sdata") {
6556 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6557 return false;
6558 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006559
Rafael Espindola870c4e92012-01-11 03:56:41 +00006560 return true;
6561}
6562
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006563bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6564 // If this is not the end of the statement, report an error.
6565 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6566 reportParseError("unexpected token, expected end of statement");
6567 return false;
6568 }
6569
6570 getTargetStreamer().reallowModuleDirective();
6571
6572 getParser().Lex(); // Eat EndOfStatement token.
6573 return false;
6574}
6575
Rafael Espindola870c4e92012-01-11 03:56:41 +00006576extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00006577 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
6578 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
6579 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
6580 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00006581}
Jack Carterb4dbc172012-09-05 23:34:03 +00006582
6583#define GET_REGISTER_MATCHER
6584#define GET_MATCHER_IMPLEMENTATION
6585#include "MipsGenAsmMatcher.inc"