blob: b51d0200b0b1a063c75be1854798d56a309a3ee7 [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"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000017#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000021#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/MC/MCParser/MCAsmLexer.h"
23#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000024#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000025#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000026#include "llvm/MC/MCStreamer.h"
27#include "llvm/MC/MCSubtargetInfo.h"
28#include "llvm/MC/MCSymbol.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000029#include "llvm/Support/Debug.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000030#include "llvm/Support/ELF.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000031#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000032#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000033#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000034#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000035#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000036
37using namespace llvm;
38
Chandler Carruthe96dd892014-04-21 22:55:11 +000039#define DEBUG_TYPE "mips-asm-parser"
40
Joey Gouly0e76fa72013-09-12 10:28:05 +000041namespace llvm {
42class MCInstrInfo;
43}
44
Rafael Espindola870c4e92012-01-11 03:56:41 +000045namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000046class MipsAssemblerOptions {
47public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000048 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000049 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000050
Toma Tabacu9db22db2014-09-09 10:15:38 +000051 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000052 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000053 Reorder = Opts->isReorder();
54 Macro = Opts->isMacro();
55 Features = Opts->getFeatures();
56 }
57
Toma Tabacub19cf202015-04-27 13:12:59 +000058 unsigned getATRegIndex() const { return ATReg; }
59 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000060 if (Reg > 31)
61 return false;
62
63 ATReg = Reg;
64 return true;
65 }
Jack Carter0b744b32012-10-04 02:29:46 +000066
Toma Tabacu9db22db2014-09-09 10:15:38 +000067 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000068 void setReorder() { Reorder = true; }
69 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000070
Toma Tabacu9db22db2014-09-09 10:15:38 +000071 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000072 void setMacro() { Macro = true; }
73 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000074
Toma Tabacu465acfd2015-06-09 13:33:26 +000075 const FeatureBitset &getFeatures() const { return Features; }
76 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000077
Daniel Sandersf0df2212014-08-04 12:20:00 +000078 // Set of features that are either architecture features or referenced
79 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
80 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
81 // The reason we need this mask is explained in the selectArch function.
82 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000083 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000084
Jack Carter0b744b32012-10-04 02:29:46 +000085private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000086 unsigned ATReg;
87 bool Reorder;
88 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000089 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000090};
91}
92
Michael Kupersteindb0712f2015-05-26 10:47:10 +000093const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
94 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
95 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
96 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
97 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
98 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
99 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
100 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
101 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
102};
103
Jack Carter0b744b32012-10-04 02:29:46 +0000104namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000105class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000106 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000107 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000108 return static_cast<MipsTargetStreamer &>(TS);
109 }
110
Eric Christophera5762812015-01-26 17:33:46 +0000111 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000112 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000113 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
114 // nullptr, which indicates that no function is currently
115 // selected. This usually happens after an '.end func'
116 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000117 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000118 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000119 bool IsCpRestoreSet;
120 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000121 unsigned CpSaveLocation;
122 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
123 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000124
Daniel Sandersef638fe2014-10-03 15:37:37 +0000125 // Print a warning along with its fix-it message at the given range.
126 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
127 SMRange Range, bool ShowColors = true);
128
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000129#define GET_ASSEMBLER_HEADER
130#include "MipsGenAsmMatcher.inc"
131
Matheus Almeida595fcab2014-06-11 15:05:56 +0000132 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
133
Chad Rosier49963552012-10-13 00:26:04 +0000134 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000135 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000136 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000137 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000138
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000139 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000140 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000141
Toma Tabacu13964452014-09-04 13:23:44 +0000142 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000143
Toma Tabacu13964452014-09-04 13:23:44 +0000144 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000145
David Blaikie960ea3f2014-06-08 16:18:35 +0000146 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
147 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000148
Craig Topper56c590a2014-04-29 07:58:02 +0000149 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000150
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000151 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
152 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000153 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000154 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000155 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
156 SMLoc S);
157 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
158 OperandMatchResultTy parseImm(OperandVector &Operands);
159 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
160 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000161 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
162 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
163 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000164
David Blaikie960ea3f2014-06-08 16:18:35 +0000165 bool searchSymbolAlias(OperandVector &Operands);
166
Toma Tabacu13964452014-09-04 13:23:44 +0000167 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000168
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000169 enum MacroExpanderResultTy {
170 MER_NotAMacro,
171 MER_Success,
172 MER_Fail,
173 };
Jack Carter30a59822012-10-04 04:03:53 +0000174
Matheus Almeida3813d572014-06-19 14:39:14 +0000175 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000176 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
177 MCStreamer &Out,
178 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000179
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000180 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
181 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000182
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000183 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000184 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000185 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000186
Toma Tabacuf712ede2015-06-17 14:31:51 +0000187 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
188 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000189 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000190
Toma Tabacu00e98672015-05-01 12:19:27 +0000191 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000192 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000193
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000194 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
195 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000196 SMLoc IDLoc, MCStreamer &Out,
197 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000198
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000199 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
200 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000201
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000202 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000203 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
204
205 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
206 const MCSubtargetInfo *STI, bool IsImmOpnd);
207
208 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
209 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000210
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000211 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
212 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000213
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000214 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
215 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000216
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000217 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
218 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000219
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000220 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
221 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000222
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000223 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
224 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000225 const bool Signed);
226
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000227 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000228 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000229
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000230 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
231 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000232
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000233 bool expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
234 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000235
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000236 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000237 MCStreamer &Out, const MCSubtargetInfo *STI);
238 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
239 const MCSubtargetInfo *STI);
240 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
241 const MCSubtargetInfo *STI);
242 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
243 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000244
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000245 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
246 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000247
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000248 bool reportParseError(Twine ErrorMsg);
249 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000250
Jack Carterb5cf5902013-04-17 00:18:04 +0000251 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000252 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000253
Vladimir Medic4c299852013-11-06 11:27:05 +0000254 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000255
256 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000257 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000258 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000259 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000260 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000261 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000262 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000263 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000264 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000265 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000266 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000267 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000268 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000269 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000270
271 bool parseSetAtDirective();
272 bool parseSetNoAtDirective();
273 bool parseSetMacroDirective();
274 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000275 bool parseSetMsaDirective();
276 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000277 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000278 bool parseSetReorderDirective();
279 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000280 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000281 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000282 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000283 bool parseSetOddSPRegDirective();
284 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000285 bool parseSetPopDirective();
286 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000287 bool parseSetSoftFloatDirective();
288 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000289
Jack Carterd76b2372013-03-21 21:44:16 +0000290 bool parseSetAssignment();
291
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000292 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000293 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000294 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000295 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000296 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000297 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
298 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000299
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000300 bool parseInternalDirectiveReallowModule();
301
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000302 bool eatComma(StringRef ErrorStr);
303
Jack Carter1ac53222013-02-20 23:11:17 +0000304 int matchCPURegisterName(StringRef Symbol);
305
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000306 int matchHWRegsRegisterName(StringRef Symbol);
307
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000308 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000309
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000310 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000311
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000312 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000313
Jack Carter5dc8ac92013-09-25 23:50:44 +0000314 int matchMSA128RegisterName(StringRef Name);
315
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000316 int matchMSA128CtrlRegisterName(StringRef Name);
317
Jack Carterd0bd6422013-04-18 00:41:53 +0000318 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000319
Toma Tabacu89a712b2015-04-15 10:48:56 +0000320 /// Returns the internal register number for the current AT. Also checks if
321 /// the current AT is unavailable (set to $0) and gives an error if it is.
322 /// This should be used in pseudo-instruction expansions which need AT.
323 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000324
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000325 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
326 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000327
328 // Helper function that checks if the value of a vector index is within the
329 // boundaries of accepted values for each RegisterKind
330 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
331 bool validateMSAIndex(int Val, int RegKind);
332
Daniel Sandersf0df2212014-08-04 12:20:00 +0000333 // Selects a new architecture by updating the FeatureBits with the necessary
334 // info including implied dependencies.
335 // Internally, it clears all the feature bits related to *any* architecture
336 // and selects the new one using the ToggleFeature functionality of the
337 // MCSubtargetInfo object that handles implied dependencies. The reason we
338 // clear all the arch related bits manually is because ToggleFeature only
339 // clears the features that imply the feature being cleared and not the
340 // features implied by the feature being cleared. This is easier to see
341 // with an example:
342 // --------------------------------------------------
343 // | Feature | Implies |
344 // | -------------------------------------------------|
345 // | FeatureMips1 | None |
346 // | FeatureMips2 | FeatureMips1 |
347 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
348 // | FeatureMips4 | FeatureMips3 |
349 // | ... | |
350 // --------------------------------------------------
351 //
352 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
353 // FeatureMipsGP64 | FeatureMips1)
354 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
355 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000356 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000357 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000358 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
359 STI.setFeatureBits(FeatureBits);
360 setAvailableFeatures(
361 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000362 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000363 }
364
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000365 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000366 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000367 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000368 setAvailableFeatures(
369 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000370 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000371 }
372 }
373
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000374 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000375 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000376 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000377 setAvailableFeatures(
378 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000379 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000380 }
381 }
382
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000383 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
384 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000385 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000386 }
387
388 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
389 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000390 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000391 }
392
Rafael Espindola870c4e92012-01-11 03:56:41 +0000393public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000394 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000395 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000396 Match_RequiresDifferentOperands,
397 Match_RequiresNoZeroRegister,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000398#define GET_OPERAND_DIAGNOSTIC_TYPES
399#include "MipsGenAsmMatcher.inc"
400#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000401 };
402
Akira Hatanakab11ef082015-11-14 06:35:56 +0000403 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000404 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000405 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000406 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
407 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000408 MCAsmParserExtension::Initialize(parser);
409
Toma Tabacu11e14a92015-04-21 11:50:52 +0000410 parser.addAliasForDirective(".asciiz", ".asciz");
411
Jack Carterb4dbc172012-09-05 23:34:03 +0000412 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000413 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000414
Toma Tabacu9db22db2014-09-09 10:15:38 +0000415 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000416 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000417 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000418
Toma Tabacu9db22db2014-09-09 10:15:38 +0000419 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000420 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000421 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000422
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000423 getTargetStreamer().updateABIInfo(*this);
424
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000425 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000426 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000427
428 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000429
Rafael Espindola699281c2016-05-18 11:58:50 +0000430 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000431
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000432 IsCpRestoreSet = false;
433 CpRestoreOffset = -1;
434
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000435 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000436 if ((TheTriple.getArch() == Triple::mips) ||
437 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000438 IsLittleEndian = false;
439 else
440 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000441 }
442
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000443 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
444 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
445
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000446 bool isGP64bit() const {
447 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
448 }
449 bool isFP64bit() const {
450 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
451 }
Eric Christophera5762812015-01-26 17:33:46 +0000452 const MipsABIInfo &getABI() const { return ABI; }
453 bool isABI_N32() const { return ABI.IsN32(); }
454 bool isABI_N64() const { return ABI.IsN64(); }
455 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000456 bool isABI_FPXX() const {
457 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
458 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000459
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000460 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000461 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000462 }
463
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000464 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000465 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000466 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000467 bool hasMips1() const {
468 return getSTI().getFeatureBits()[Mips::FeatureMips1];
469 }
470 bool hasMips2() const {
471 return getSTI().getFeatureBits()[Mips::FeatureMips2];
472 }
473 bool hasMips3() const {
474 return getSTI().getFeatureBits()[Mips::FeatureMips3];
475 }
476 bool hasMips4() const {
477 return getSTI().getFeatureBits()[Mips::FeatureMips4];
478 }
479 bool hasMips5() const {
480 return getSTI().getFeatureBits()[Mips::FeatureMips5];
481 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000482 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000483 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000484 }
485 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000486 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000487 }
488 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000489 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000490 }
491 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000492 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000493 }
Daniel Sanders17793142015-02-18 16:24:50 +0000494 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000495 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000496 }
497 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000498 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000499 }
500 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000501 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000502 }
503 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000504 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000505 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000506 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000507 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000508 }
509 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000510 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000511 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000512
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000513 bool hasDSP() const {
514 return getSTI().getFeatureBits()[Mips::FeatureDSP];
515 }
516 bool hasDSPR2() const {
517 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
518 }
519 bool hasDSPR3() const {
520 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
521 }
522 bool hasMSA() const {
523 return getSTI().getFeatureBits()[Mips::FeatureMSA];
524 }
Kai Nackee0245392015-01-27 19:11:28 +0000525 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000526 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000527 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000528
Daniel Sandersa6994442015-08-18 12:33:54 +0000529 bool inPicMode() {
530 return IsPicEnabled;
531 }
532
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000533 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000534 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000535 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000536
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000537 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000538 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000539 }
540
Eric Christophere8ae3e32015-05-07 23:10:21 +0000541 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000542 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000543 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000544
Toma Tabacud9d344b2015-04-27 14:05:04 +0000545 /// Warn if RegIndex is the same as the current AT.
546 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000547
548 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000549
550 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000551};
552}
553
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000554namespace {
555
556/// MipsOperand - Instances of this class represent a parsed Mips machine
557/// instruction.
558class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000559public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000560 /// Broad categories of register classes
561 /// The exact class is finalized by the render method.
562 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000563 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000564 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000565 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000566 RegKind_FCC = 4, /// FCC
567 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
568 RegKind_MSACtrl = 16, /// MSA control registers
569 RegKind_COP2 = 32, /// COP2
570 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
571 /// context).
572 RegKind_CCR = 128, /// CCR
573 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000574 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000575 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000576 /// Potentially any (e.g. $1)
577 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
578 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000579 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000580 };
581
582private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000583 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000584 k_Immediate, /// An immediate (possibly involving symbol references)
585 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000586 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000587 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000588 k_RegList, /// A physical register list
589 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000590 } Kind;
591
David Blaikie960ea3f2014-06-08 16:18:35 +0000592public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000593 MipsOperand(KindTy K, MipsAsmParser &Parser)
594 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
595
David Blaikie960ea3f2014-06-08 16:18:35 +0000596private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000597 /// For diagnostics, and checking the assembler temporary
598 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000599
Eric Christopher8996c5d2013-03-15 00:42:55 +0000600 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000601 const char *Data;
602 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000603 };
604
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000605 struct RegIdxOp {
606 unsigned Index; /// Index into the register class
607 RegKind Kind; /// Bitfield of the kinds it could possibly be
608 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000609 };
610
611 struct ImmOp {
612 const MCExpr *Val;
613 };
614
615 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000616 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000617 const MCExpr *Off;
618 };
619
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000620 struct RegListOp {
621 SmallVector<unsigned, 10> *List;
622 };
623
Jack Carterb4dbc172012-09-05 23:34:03 +0000624 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000625 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000626 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000627 struct ImmOp Imm;
628 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000629 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000630 };
631
632 SMLoc StartLoc, EndLoc;
633
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000634 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000635 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
636 const MCRegisterInfo *RegInfo,
637 SMLoc S, SMLoc E,
638 MipsAsmParser &Parser) {
639 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000640 Op->RegIdx.Index = Index;
641 Op->RegIdx.RegInfo = RegInfo;
642 Op->RegIdx.Kind = RegKind;
643 Op->StartLoc = S;
644 Op->EndLoc = E;
645 return Op;
646 }
647
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000648public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000649 /// Coerce the register to GPR32 and return the real register for the current
650 /// target.
651 unsigned getGPR32Reg() const {
652 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000653 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000654 unsigned ClassID = Mips::GPR32RegClassID;
655 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000656 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000657
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000658 /// Coerce the register to GPR32 and return the real register for the current
659 /// target.
660 unsigned getGPRMM16Reg() const {
661 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
662 unsigned ClassID = Mips::GPR32RegClassID;
663 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
664 }
665
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000666 /// Coerce the register to GPR64 and return the real register for the current
667 /// target.
668 unsigned getGPR64Reg() const {
669 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
670 unsigned ClassID = Mips::GPR64RegClassID;
671 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000672 }
673
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000674private:
675 /// Coerce the register to AFGR64 and return the real register for the current
676 /// target.
677 unsigned getAFGR64Reg() const {
678 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
679 if (RegIdx.Index % 2 != 0)
680 AsmParser.Warning(StartLoc, "Float register should be even.");
681 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
682 .getRegister(RegIdx.Index / 2);
683 }
684
685 /// Coerce the register to FGR64 and return the real register for the current
686 /// target.
687 unsigned getFGR64Reg() const {
688 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
689 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
690 .getRegister(RegIdx.Index);
691 }
692
693 /// Coerce the register to FGR32 and return the real register for the current
694 /// target.
695 unsigned getFGR32Reg() const {
696 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
697 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
698 .getRegister(RegIdx.Index);
699 }
700
701 /// Coerce the register to FGRH32 and return the real register for the current
702 /// target.
703 unsigned getFGRH32Reg() const {
704 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
705 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
706 .getRegister(RegIdx.Index);
707 }
708
709 /// Coerce the register to FCC and return the real register for the current
710 /// target.
711 unsigned getFCCReg() const {
712 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
713 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
714 .getRegister(RegIdx.Index);
715 }
716
717 /// Coerce the register to MSA128 and return the real register for the current
718 /// target.
719 unsigned getMSA128Reg() const {
720 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
721 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
722 // identical
723 unsigned ClassID = Mips::MSA128BRegClassID;
724 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
725 }
726
727 /// Coerce the register to MSACtrl and return the real register for the
728 /// current target.
729 unsigned getMSACtrlReg() const {
730 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
731 unsigned ClassID = Mips::MSACtrlRegClassID;
732 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
733 }
734
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000735 /// Coerce the register to COP0 and return the real register for the
736 /// current target.
737 unsigned getCOP0Reg() const {
738 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
739 unsigned ClassID = Mips::COP0RegClassID;
740 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
741 }
742
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000743 /// Coerce the register to COP2 and return the real register for the
744 /// current target.
745 unsigned getCOP2Reg() const {
746 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
747 unsigned ClassID = Mips::COP2RegClassID;
748 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
749 }
750
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000751 /// Coerce the register to COP3 and return the real register for the
752 /// current target.
753 unsigned getCOP3Reg() const {
754 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
755 unsigned ClassID = Mips::COP3RegClassID;
756 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
757 }
758
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000759 /// Coerce the register to ACC64DSP and return the real register for the
760 /// current target.
761 unsigned getACC64DSPReg() const {
762 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
763 unsigned ClassID = Mips::ACC64DSPRegClassID;
764 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
765 }
766
767 /// Coerce the register to HI32DSP and return the real register for the
768 /// current target.
769 unsigned getHI32DSPReg() const {
770 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
771 unsigned ClassID = Mips::HI32DSPRegClassID;
772 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
773 }
774
775 /// Coerce the register to LO32DSP and return the real register for the
776 /// current target.
777 unsigned getLO32DSPReg() const {
778 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
779 unsigned ClassID = Mips::LO32DSPRegClassID;
780 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
781 }
782
783 /// Coerce the register to CCR and return the real register for the
784 /// current target.
785 unsigned getCCRReg() const {
786 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
787 unsigned ClassID = Mips::CCRRegClassID;
788 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
789 }
790
791 /// Coerce the register to HWRegs and return the real register for the
792 /// current target.
793 unsigned getHWRegsReg() const {
794 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
795 unsigned ClassID = Mips::HWRegsRegClassID;
796 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
797 }
798
799public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000800 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000801 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000802 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000803 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000804 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000805 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000806 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000807 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000808 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000809
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000810 void addRegOperands(MCInst &Inst, unsigned N) const {
811 llvm_unreachable("Use a custom parser instead");
812 }
813
Daniel Sanders21bce302014-04-01 12:35:23 +0000814 /// Render the operand to an MCInst as a GPR32
815 /// Asserts if the wrong number of operands are requested, or the operand
816 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000817 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
818 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000819 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000820 }
821
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000822 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
823 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000824 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000825 }
826
Jozef Kolek1904fa22014-11-24 14:25:53 +0000827 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
828 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000829 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000830 }
831
Zoran Jovanovic41688672015-02-10 16:36:20 +0000832 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
833 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000834 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000835 }
836
Daniel Sanders21bce302014-04-01 12:35:23 +0000837 /// Render the operand to an MCInst as a GPR64
838 /// Asserts if the wrong number of operands are requested, or the operand
839 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000840 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
841 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000842 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000843 }
844
845 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
846 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000847 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000848 }
849
850 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
851 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000852 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000853 }
854
855 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
856 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000857 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000858 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000859 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000860 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
861 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000862 }
863
864 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
865 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000866 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000867 }
868
869 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
870 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000871 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000872 }
873
874 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
875 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000876 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000877 }
878
879 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
880 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000881 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000882 }
883
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000884 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
885 assert(N == 1 && "Invalid number of operands!");
886 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
887 }
888
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000889 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
890 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000891 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000892 }
893
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000894 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
895 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000896 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000897 }
898
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000899 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
900 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000901 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000902 }
903
904 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
905 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000906 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000907 }
908
909 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
910 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000911 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000912 }
913
914 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
915 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000916 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000917 }
918
919 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
920 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000921 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000922 }
923
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000924 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000925 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
926 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000927 uint64_t Imm = getConstantImm() - Offset;
928 Imm &= (1 << Bits) - 1;
929 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000930 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000931 Inst.addOperand(MCOperand::createImm(Imm));
932 }
933
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000934 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +0000935 void addSImmOperands(MCInst &Inst, unsigned N) const {
936 if (isImm() && !isConstantImm()) {
937 addExpr(Inst, getImm());
938 return;
939 }
940 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
941 }
942
943 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000944 void addUImmOperands(MCInst &Inst, unsigned N) const {
945 if (isImm() && !isConstantImm()) {
946 addExpr(Inst, getImm());
947 return;
948 }
949 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
950 }
951
Daniel Sanders78e89022016-03-11 11:37:50 +0000952 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
953 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
954 assert(N == 1 && "Invalid number of operands!");
955 int64_t Imm = getConstantImm() - Offset;
956 Imm = SignExtend64<Bits>(Imm);
957 Imm += Offset;
958 Imm += AdjustOffset;
959 Inst.addOperand(MCOperand::createImm(Imm));
960 }
961
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000962 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000963 assert(N == 1 && "Invalid number of operands!");
964 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000965 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000966 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000967
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000968 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000969 assert(N == 2 && "Invalid number of operands!");
970
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000971 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
972 ? getMemBase()->getGPR64Reg()
973 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000974
975 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000976 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000977 }
978
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000979 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
980 assert(N == 2 && "Invalid number of operands!");
981
Jim Grosbache9119e42015-05-13 18:37:00 +0000982 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000983
984 const MCExpr *Expr = getMemOff();
985 addExpr(Inst, Expr);
986 }
987
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000988 void addRegListOperands(MCInst &Inst, unsigned N) const {
989 assert(N == 1 && "Invalid number of operands!");
990
991 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000992 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000993 }
994
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000995 void addRegPairOperands(MCInst &Inst, unsigned N) const {
996 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +0000997 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000998 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +0000999 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1000 Inst.addOperand(MCOperand::createReg(
1001 RegIdx.RegInfo->getRegClass(
1002 AsmParser.getABI().AreGprs64bit()
1003 ? Mips::GPR64RegClassID
1004 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1005 Inst.addOperand(MCOperand::createReg(
1006 RegIdx.RegInfo->getRegClass(
1007 AsmParser.getABI().AreGprs64bit()
1008 ? Mips::GPR64RegClassID
1009 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001010 }
1011
Zoran Jovanovic41688672015-02-10 16:36:20 +00001012 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1013 assert(N == 2 && "Invalid number of operands!");
1014 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001015 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001016 }
1017
Craig Topper56c590a2014-04-29 07:58:02 +00001018 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001019 // As a special case until we sort out the definition of div/divu, accept
1020 // $0/$zero here so that MCK_ZERO works correctly.
1021 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001022 }
1023 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001024 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001025 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +00001026 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001027 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001028 bool isConstantImmz() const {
1029 return isConstantImm() && getConstantImm() == 0;
1030 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001031 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1032 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1033 }
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001034 template <unsigned Bits> bool isSImm() const {
1035 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1036 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001037 template <unsigned Bits> bool isUImm() const {
1038 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1039 }
1040 template <unsigned Bits> bool isAnyImm() const {
1041 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1042 isUInt<Bits>(getConstantImm()))
1043 : isImm();
1044 }
Daniel Sanders78e89022016-03-11 11:37:50 +00001045 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1046 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001047 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001048 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1049 return isConstantImm() && getConstantImm() >= Bottom &&
1050 getConstantImm() <= Top;
1051 }
Craig Topper56c590a2014-04-29 07:58:02 +00001052 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001053 // Note: It's not possible to pretend that other operand kinds are tokens.
1054 // The matcher emitter checks tokens first.
1055 return Kind == k_Token;
1056 }
Craig Topper56c590a2014-04-29 07:58:02 +00001057 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001058 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001059 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001060 }
Simon Dardis4ccda502016-05-27 13:56:36 +00001061 // Allow relocation operators.
1062 // FIXME: This predicate and others need to look through binary expressions
1063 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001064 template <unsigned Bits, unsigned ShiftAmount = 0>
1065 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001066 if (!isMem())
1067 return false;
1068 if (!getMemBase()->isGPRAsmReg())
1069 return false;
1070 if (isa<MCTargetExpr>(getMemOff()) ||
1071 (isConstantMemOff() &&
1072 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1073 return true;
1074 MCValue Res;
1075 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1076 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001077 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001078 bool isMemWithGRPMM16Base() const {
1079 return isMem() && getMemBase()->isMM16AsmReg();
1080 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001081 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1082 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1083 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1084 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001085 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1086 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1087 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1088 && (getMemBase()->getGPR32Reg() == Mips::SP);
1089 }
Daniel Sanderse473dc92016-05-09 13:38:25 +00001090 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1091 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1092 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1093 && (getMemBase()->getGPR32Reg() == Mips::GP);
1094 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001095 template <unsigned Bits, unsigned ShiftLeftAmount>
1096 bool isScaledUImm() const {
1097 return isConstantImm() &&
1098 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001099 }
Daniel Sanders97297772016-03-22 14:40:00 +00001100 template <unsigned Bits, unsigned ShiftLeftAmount>
1101 bool isScaledSImm() const {
1102 return isConstantImm() &&
1103 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
1104 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001105 bool isRegList16() const {
1106 if (!isRegList())
1107 return false;
1108
1109 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001110 if (Size < 2 || Size > 5)
1111 return false;
1112
1113 unsigned R0 = RegList.List->front();
1114 unsigned R1 = RegList.List->back();
1115 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1116 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001117 return false;
1118
1119 int PrevReg = *RegList.List->begin();
1120 for (int i = 1; i < Size - 1; i++) {
1121 int Reg = (*(RegList.List))[i];
1122 if ( Reg != PrevReg + 1)
1123 return false;
1124 PrevReg = Reg;
1125 }
1126
1127 return true;
1128 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001129 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001130 bool isLSAImm() const {
1131 if (!isConstantImm())
1132 return false;
1133 int64_t Val = getConstantImm();
1134 return 1 <= Val && Val <= 4;
1135 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001136 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001137 bool isMovePRegPair() const {
1138 if (Kind != k_RegList || RegList.List->size() != 2)
1139 return false;
1140
1141 unsigned R0 = RegList.List->front();
1142 unsigned R1 = RegList.List->back();
1143
1144 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1145 (R0 == Mips::A1 && R1 == Mips::A3) ||
1146 (R0 == Mips::A2 && R1 == Mips::A3) ||
1147 (R0 == Mips::A0 && R1 == Mips::S5) ||
1148 (R0 == Mips::A0 && R1 == Mips::S6) ||
1149 (R0 == Mips::A0 && R1 == Mips::A1) ||
1150 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001151 (R0 == Mips::A0 && R1 == Mips::A3) ||
1152 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1153 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1154 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1155 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1156 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1157 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1158 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1159 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001160 return true;
1161
1162 return false;
1163 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001164
1165 StringRef getToken() const {
1166 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001167 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001168 }
Zlatko Buljanba553a62016-05-09 08:07:28 +00001169 bool isRegPair() const {
1170 return Kind == k_RegPair && RegIdx.Index <= 30;
1171 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001172
Craig Topper56c590a2014-04-29 07:58:02 +00001173 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001174 // As a special case until we sort out the definition of div/divu, accept
1175 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001176 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1177 RegIdx.Kind & RegKind_GPR)
1178 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001179
Daniel Sanders976d9382016-07-05 13:38:40 +00001180 llvm_unreachable("Invalid access!");
1181 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001182 }
1183
Jack Carterb4dbc172012-09-05 23:34:03 +00001184 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001185 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001186 return Imm.Val;
1187 }
1188
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001189 int64_t getConstantImm() const {
1190 const MCExpr *Val = getImm();
1191 return static_cast<const MCConstantExpr *>(Val)->getValue();
1192 }
1193
1194 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001195 assert((Kind == k_Memory) && "Invalid access!");
1196 return Mem.Base;
1197 }
1198
1199 const MCExpr *getMemOff() const {
1200 assert((Kind == k_Memory) && "Invalid access!");
1201 return Mem.Off;
1202 }
1203
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001204 int64_t getConstantMemOff() const {
1205 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1206 }
1207
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001208 const SmallVectorImpl<unsigned> &getRegList() const {
1209 assert((Kind == k_RegList) && "Invalid access!");
1210 return *(RegList.List);
1211 }
1212
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001213 unsigned getRegPair() const {
1214 assert((Kind == k_RegPair) && "Invalid access!");
1215 return RegIdx.Index;
1216 }
1217
David Blaikie960ea3f2014-06-08 16:18:35 +00001218 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1219 MipsAsmParser &Parser) {
1220 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001221 Op->Tok.Data = Str.data();
1222 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001223 Op->StartLoc = S;
1224 Op->EndLoc = S;
1225 return Op;
1226 }
1227
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001228 /// Create a numeric register (e.g. $1). The exact register remains
1229 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001230 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001231 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001232 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001233 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001234 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001235 }
1236
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001237 /// Create a register that is definitely a GPR.
1238 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001239 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001240 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001241 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001242 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001243 }
1244
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001245 /// Create a register that is definitely a FGR.
1246 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001247 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001248 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001249 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001250 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1251 }
1252
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001253 /// Create a register that is definitely a HWReg.
1254 /// This is typically only used for named registers such as $hwr_cpunum.
1255 static std::unique_ptr<MipsOperand>
1256 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1257 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1258 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1259 }
1260
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001261 /// Create a register that is definitely an FCC.
1262 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001263 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001264 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001265 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001266 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1267 }
1268
1269 /// Create a register that is definitely an ACC.
1270 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001271 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001272 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001273 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001274 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1275 }
1276
1277 /// Create a register that is definitely an MSA128.
1278 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001279 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001280 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001281 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001282 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1283 }
1284
1285 /// Create a register that is definitely an MSACtrl.
1286 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001287 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001288 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001289 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001290 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1291 }
1292
David Blaikie960ea3f2014-06-08 16:18:35 +00001293 static std::unique_ptr<MipsOperand>
1294 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1295 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001296 Op->Imm.Val = Val;
1297 Op->StartLoc = S;
1298 Op->EndLoc = E;
1299 return Op;
1300 }
1301
David Blaikie960ea3f2014-06-08 16:18:35 +00001302 static std::unique_ptr<MipsOperand>
1303 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1304 SMLoc E, MipsAsmParser &Parser) {
1305 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1306 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001307 Op->Mem.Off = Off;
1308 Op->StartLoc = S;
1309 Op->EndLoc = E;
1310 return Op;
1311 }
1312
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001313 static std::unique_ptr<MipsOperand>
1314 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1315 MipsAsmParser &Parser) {
1316 assert (Regs.size() > 0 && "Empty list not allowed");
1317
1318 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001319 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001320 Op->StartLoc = StartLoc;
1321 Op->EndLoc = EndLoc;
1322 return Op;
1323 }
1324
Daniel Sandersd044e492016-05-09 13:10:57 +00001325 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1326 SMLoc S, SMLoc E,
1327 MipsAsmParser &Parser) {
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001328 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001329 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001330 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1331 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001332 Op->StartLoc = S;
1333 Op->EndLoc = E;
1334 return Op;
1335 }
1336
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001337 bool isGPRAsmReg() const {
1338 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001339 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001340 bool isMM16AsmReg() const {
1341 if (!(isRegIdx() && RegIdx.Kind))
1342 return false;
1343 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1344 || RegIdx.Index == 16 || RegIdx.Index == 17);
1345 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001346 bool isMM16AsmRegZero() const {
1347 if (!(isRegIdx() && RegIdx.Kind))
1348 return false;
1349 return (RegIdx.Index == 0 ||
1350 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1351 RegIdx.Index == 17);
1352 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001353 bool isMM16AsmRegMoveP() const {
1354 if (!(isRegIdx() && RegIdx.Kind))
1355 return false;
1356 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1357 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1358 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001359 bool isFGRAsmReg() const {
1360 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1361 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001362 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001363 bool isHWRegsAsmReg() const {
1364 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001365 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001366 bool isCCRAsmReg() const {
1367 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001368 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001369 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001370 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1371 return false;
1372 if (!AsmParser.hasEightFccRegisters())
1373 return RegIdx.Index == 0;
1374 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001375 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001376 bool isACCAsmReg() const {
1377 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001378 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001379 bool isCOP0AsmReg() const {
1380 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1381 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001382 bool isCOP2AsmReg() const {
1383 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001384 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001385 bool isCOP3AsmReg() const {
1386 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1387 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001388 bool isMSA128AsmReg() const {
1389 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001390 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001391 bool isMSACtrlAsmReg() const {
1392 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001393 }
1394
Jack Carterb4dbc172012-09-05 23:34:03 +00001395 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001396 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001397 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001398 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001399
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001400 virtual ~MipsOperand() {
1401 switch (Kind) {
1402 case k_Immediate:
1403 break;
1404 case k_Memory:
1405 delete Mem.Base;
1406 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001407 case k_RegList:
1408 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001409 case k_RegisterIndex:
1410 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001411 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001412 break;
1413 }
1414 }
1415
Craig Topper56c590a2014-04-29 07:58:02 +00001416 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001417 switch (Kind) {
1418 case k_Immediate:
1419 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001420 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001421 OS << ">";
1422 break;
1423 case k_Memory:
1424 OS << "Mem<";
1425 Mem.Base->print(OS);
1426 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001427 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001428 OS << ">";
1429 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001430 case k_RegisterIndex:
1431 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1432 break;
1433 case k_Token:
Daniel Sanders7b361a22016-07-05 10:44:24 +00001434 OS << Tok.Data;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001435 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001436 case k_RegList:
1437 OS << "RegList< ";
1438 for (auto Reg : (*RegList.List))
1439 OS << Reg << " ";
1440 OS << ">";
1441 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001442 case k_RegPair:
1443 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1444 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001445 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001446 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001447}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001448} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001449
Jack Carter9e65aa32013-03-22 00:05:30 +00001450namespace llvm {
1451extern const MCInstrDesc MipsInsts[];
1452}
1453static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1454 return MipsInsts[Opcode];
1455}
1456
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001457static bool hasShortDelaySlot(unsigned Opcode) {
1458 switch (Opcode) {
1459 case Mips::JALS_MM:
1460 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001461 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001462 case Mips::BGEZALS_MM:
1463 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001464 return true;
1465 default:
1466 return false;
1467 }
1468}
1469
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001470static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1471 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1472 return &SRExpr->getSymbol();
1473 }
1474
1475 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1476 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1477 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1478
1479 if (LHSSym)
1480 return LHSSym;
1481
1482 if (RHSSym)
1483 return RHSSym;
1484
1485 return nullptr;
1486 }
1487
1488 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1489 return getSingleMCSymbol(UExpr->getSubExpr());
1490
1491 return nullptr;
1492}
1493
1494static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1495 if (isa<MCSymbolRefExpr>(Expr))
1496 return 1;
1497
1498 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1499 return countMCSymbolRefExpr(BExpr->getLHS()) +
1500 countMCSymbolRefExpr(BExpr->getRHS());
1501
1502 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1503 return countMCSymbolRefExpr(UExpr->getSubExpr());
1504
1505 return 0;
1506}
1507
Jack Carter9e65aa32013-03-22 00:05:30 +00001508bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001509 MCStreamer &Out,
1510 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001511 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001512 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001513 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001514
Jack Carter9e65aa32013-03-22 00:05:30 +00001515 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001516
1517 if (MCID.isBranch() || MCID.isCall()) {
1518 const unsigned Opcode = Inst.getOpcode();
1519 MCOperand Offset;
1520
1521 switch (Opcode) {
1522 default:
1523 break;
Kai Nackee0245392015-01-27 19:11:28 +00001524 case Mips::BBIT0:
1525 case Mips::BBIT032:
1526 case Mips::BBIT1:
1527 case Mips::BBIT132:
1528 assert(hasCnMips() && "instruction only valid for octeon cpus");
1529 // Fall through
1530
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001531 case Mips::BEQ:
1532 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001533 case Mips::BEQ_MM:
1534 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001535 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001536 Offset = Inst.getOperand(2);
1537 if (!Offset.isImm())
1538 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001539 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001540 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001541 if (OffsetToAlignment(Offset.getImm(),
1542 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001543 return Error(IDLoc, "branch to misaligned address");
1544 break;
1545 case Mips::BGEZ:
1546 case Mips::BGTZ:
1547 case Mips::BLEZ:
1548 case Mips::BLTZ:
1549 case Mips::BGEZAL:
1550 case Mips::BLTZAL:
1551 case Mips::BC1F:
1552 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001553 case Mips::BGEZ_MM:
1554 case Mips::BGTZ_MM:
1555 case Mips::BLEZ_MM:
1556 case Mips::BLTZ_MM:
1557 case Mips::BGEZAL_MM:
1558 case Mips::BLTZAL_MM:
1559 case Mips::BC1F_MM:
1560 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001561 case Mips::BC1EQZC_MMR6:
1562 case Mips::BC1NEZC_MMR6:
1563 case Mips::BC2EQZC_MMR6:
1564 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001565 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001566 Offset = Inst.getOperand(1);
1567 if (!Offset.isImm())
1568 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001569 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001570 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001571 if (OffsetToAlignment(Offset.getImm(),
1572 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001573 return Error(IDLoc, "branch to misaligned address");
1574 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001575 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001576 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001577 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001578 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001579 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1580 Offset = Inst.getOperand(1);
1581 if (!Offset.isImm())
1582 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001583 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001584 return Error(IDLoc, "branch target out of range");
1585 if (OffsetToAlignment(Offset.getImm(), 2LL))
1586 return Error(IDLoc, "branch to misaligned address");
1587 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001588 }
1589 }
1590
Daniel Sandersa84989a2014-06-16 13:25:35 +00001591 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1592 // We still accept it but it is a normal nop.
1593 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1594 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1595 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1596 "nop instruction");
1597 }
1598
Kai Nackee0245392015-01-27 19:11:28 +00001599 if (hasCnMips()) {
1600 const unsigned Opcode = Inst.getOpcode();
1601 MCOperand Opnd;
1602 int Imm;
1603
1604 switch (Opcode) {
1605 default:
1606 break;
1607
1608 case Mips::BBIT0:
1609 case Mips::BBIT032:
1610 case Mips::BBIT1:
1611 case Mips::BBIT132:
1612 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1613 // The offset is handled above
1614 Opnd = Inst.getOperand(1);
1615 if (!Opnd.isImm())
1616 return Error(IDLoc, "expected immediate operand kind");
1617 Imm = Opnd.getImm();
1618 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1619 Opcode == Mips::BBIT1 ? 63 : 31))
1620 return Error(IDLoc, "immediate operand value out of range");
1621 if (Imm > 31) {
1622 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1623 : Mips::BBIT132);
1624 Inst.getOperand(1).setImm(Imm - 32);
1625 }
1626 break;
1627
Kai Nackee0245392015-01-27 19:11:28 +00001628 case Mips::SEQi:
1629 case Mips::SNEi:
1630 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1631 Opnd = Inst.getOperand(2);
1632 if (!Opnd.isImm())
1633 return Error(IDLoc, "expected immediate operand kind");
1634 Imm = Opnd.getImm();
1635 if (!isInt<10>(Imm))
1636 return Error(IDLoc, "immediate operand value out of range");
1637 break;
1638 }
1639 }
1640
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001641 // This expansion is not in a function called by tryExpandInstruction()
1642 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001643 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1644 inPicMode()) {
1645 warnIfNoMacro(IDLoc);
1646
1647 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1648
1649 // We can do this expansion if there's only 1 symbol in the argument
1650 // expression.
1651 if (countMCSymbolRefExpr(JalExpr) > 1)
1652 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1653
1654 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001655 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001656 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1657
1658 // FIXME: Add support for label+offset operands (currently causes an error).
1659 // FIXME: Add support for forward-declared local symbols.
1660 // FIXME: Add expansion for when the LargeGOT option is enabled.
1661 if (JalSym->isInSection() || JalSym->isTemporary()) {
1662 if (isABI_O32()) {
1663 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001664 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001665 // R_(MICRO)MIPS_GOT16 label
1666 // addiu $25, $25, 0
1667 // R_(MICRO)MIPS_LO16 label
1668 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001669 const MCExpr *Got16RelocExpr =
1670 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1671 const MCExpr *Lo16RelocExpr =
1672 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001673
Daniel Sandersa736b372016-04-29 13:33:12 +00001674 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1675 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1676 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1677 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001678 } else if (isABI_N32() || isABI_N64()) {
1679 // If it's a local symbol and the N32/N64 ABIs are being used,
1680 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001681 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001682 // R_(MICRO)MIPS_GOT_DISP label
1683 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001684 const MCExpr *GotDispRelocExpr =
1685 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001686
Daniel Sandersa736b372016-04-29 13:33:12 +00001687 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1688 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1689 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001690 }
1691 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001692 // If it's an external/weak symbol, we expand to:
1693 // lw/ld $25, 0($gp)
1694 // R_(MICRO)MIPS_CALL16 label
1695 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001696 const MCExpr *Call16RelocExpr =
1697 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001698
Daniel Sandersa736b372016-04-29 13:33:12 +00001699 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1700 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001701 }
1702
1703 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001704 if (IsCpRestoreSet && inMicroMipsMode())
1705 JalrInst.setOpcode(Mips::JALRS_MM);
1706 else
1707 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001708 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1709 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1710
1711 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1712 // This relocation is supposed to be an optimization hint for the linker
1713 // and is not necessary for correctness.
1714
1715 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001716 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001717 }
1718
Jack Carter9e65aa32013-03-22 00:05:30 +00001719 if (MCID.mayLoad() || MCID.mayStore()) {
1720 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001721 // reference or immediate we may have to expand instructions.
1722 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001723 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001724 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1725 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001726 MCOperand &Op = Inst.getOperand(i);
1727 if (Op.isImm()) {
1728 int MemOffset = Op.getImm();
1729 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001730 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001731 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001732 return false;
1733 }
1734 } else if (Op.isExpr()) {
1735 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001736 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001737 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001738 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001739 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001740 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001741 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001742 return false;
1743 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001744 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001745 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001746 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001747 }
1748 }
1749 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001750 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001751 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001752
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001753 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001754 if (MCID.mayLoad()) {
1755 // Try to create 16-bit GP relative load instruction.
1756 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1757 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1758 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1759 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1760 MCOperand &Op = Inst.getOperand(i);
1761 if (Op.isImm()) {
1762 int MemOffset = Op.getImm();
1763 MCOperand &DstReg = Inst.getOperand(0);
1764 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001765 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001766 getContext().getRegisterInfo()->getRegClass(
1767 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001768 (BaseReg.getReg() == Mips::GP ||
1769 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001770
Daniel Sandersa736b372016-04-29 13:33:12 +00001771 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1772 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001773 return false;
1774 }
1775 }
1776 }
1777 } // for
1778 } // if load
1779
1780 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1781
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001782 MCOperand Opnd;
1783 int Imm;
1784
1785 switch (Inst.getOpcode()) {
1786 default:
1787 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001788 case Mips::ADDIUSP_MM:
1789 Opnd = Inst.getOperand(0);
1790 if (!Opnd.isImm())
1791 return Error(IDLoc, "expected immediate operand kind");
1792 Imm = Opnd.getImm();
1793 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1794 Imm % 4 != 0)
1795 return Error(IDLoc, "immediate operand value out of range");
1796 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001797 case Mips::SLL16_MM:
1798 case Mips::SRL16_MM:
1799 Opnd = Inst.getOperand(2);
1800 if (!Opnd.isImm())
1801 return Error(IDLoc, "expected immediate operand kind");
1802 Imm = Opnd.getImm();
1803 if (Imm < 1 || Imm > 8)
1804 return Error(IDLoc, "immediate operand value out of range");
1805 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001806 case Mips::LI16_MM:
1807 Opnd = Inst.getOperand(1);
1808 if (!Opnd.isImm())
1809 return Error(IDLoc, "expected immediate operand kind");
1810 Imm = Opnd.getImm();
1811 if (Imm < -1 || Imm > 126)
1812 return Error(IDLoc, "immediate operand value out of range");
1813 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001814 case Mips::ADDIUR2_MM:
1815 Opnd = Inst.getOperand(2);
1816 if (!Opnd.isImm())
1817 return Error(IDLoc, "expected immediate operand kind");
1818 Imm = Opnd.getImm();
1819 if (!(Imm == 1 || Imm == -1 ||
1820 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1821 return Error(IDLoc, "immediate operand value out of range");
1822 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001823 case Mips::ANDI16_MM:
1824 Opnd = Inst.getOperand(2);
1825 if (!Opnd.isImm())
1826 return Error(IDLoc, "expected immediate operand kind");
1827 Imm = Opnd.getImm();
1828 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1829 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1830 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1831 return Error(IDLoc, "immediate operand value out of range");
1832 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001833 case Mips::LBU16_MM:
1834 Opnd = Inst.getOperand(2);
1835 if (!Opnd.isImm())
1836 return Error(IDLoc, "expected immediate operand kind");
1837 Imm = Opnd.getImm();
1838 if (Imm < -1 || Imm > 14)
1839 return Error(IDLoc, "immediate operand value out of range");
1840 break;
1841 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001842 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001843 Opnd = Inst.getOperand(2);
1844 if (!Opnd.isImm())
1845 return Error(IDLoc, "expected immediate operand kind");
1846 Imm = Opnd.getImm();
1847 if (Imm < 0 || Imm > 15)
1848 return Error(IDLoc, "immediate operand value out of range");
1849 break;
1850 case Mips::LHU16_MM:
1851 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001852 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001853 Opnd = Inst.getOperand(2);
1854 if (!Opnd.isImm())
1855 return Error(IDLoc, "expected immediate operand kind");
1856 Imm = Opnd.getImm();
1857 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1858 return Error(IDLoc, "immediate operand value out of range");
1859 break;
1860 case Mips::LW16_MM:
1861 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001862 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001863 Opnd = Inst.getOperand(2);
1864 if (!Opnd.isImm())
1865 return Error(IDLoc, "expected immediate operand kind");
1866 Imm = Opnd.getImm();
1867 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1868 return Error(IDLoc, "immediate operand value out of range");
1869 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001870 case Mips::ADDIUPC_MM:
1871 MCOperand Opnd = Inst.getOperand(1);
1872 if (!Opnd.isImm())
1873 return Error(IDLoc, "expected immediate operand kind");
1874 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001875 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001876 return Error(IDLoc, "immediate operand value out of range");
1877 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001878 }
1879 }
1880
Daniel Sandersd8c07762016-04-18 12:35:36 +00001881 bool FillDelaySlot =
1882 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
1883 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00001884 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001885
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001886 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001887 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001888 switch (ExpandResult) {
1889 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001890 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001891 break;
1892 case MER_Success:
1893 break;
1894 case MER_Fail:
1895 return true;
1896 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001897
Daniel Sanderscda908a2016-05-16 09:10:13 +00001898 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
1899 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
1900 if (inMicroMipsMode())
1901 TOut.setUsesMicroMips();
1902
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001903 // If this instruction has a delay slot and .set reorder is active,
1904 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00001905 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001906 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
1907 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001908 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001909
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001910 if ((Inst.getOpcode() == Mips::JalOneReg ||
1911 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1912 isPicAndNotNxxAbi()) {
1913 if (IsCpRestoreSet) {
1914 // We need a NOP between the JALR and the LW:
1915 // If .set reorder has been used, we've already emitted a NOP.
1916 // If .set noreorder has been used, we need to emit a NOP at this point.
1917 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00001918 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
1919 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001920
1921 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00001922 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001923 } else
1924 Warning(IDLoc, "no .cprestore used in PIC mode");
1925 }
1926
Jack Carter9e65aa32013-03-22 00:05:30 +00001927 return false;
1928}
1929
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001930MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001931MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
1932 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001933 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001934 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001935 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001936 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001937 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001938 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001939 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001940 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001941 case Mips::LoadAddrImm64:
1942 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1943 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1944 "expected immediate operand kind");
1945
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001946 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1947 Inst.getOperand(1),
1948 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001949 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001950 ? MER_Fail
1951 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001952 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001953 case Mips::LoadAddrReg64:
1954 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1955 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1956 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1957 "expected immediate operand kind");
1958
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001959 return expandLoadAddress(Inst.getOperand(0).getReg(),
1960 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1961 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001962 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001963 ? MER_Fail
1964 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001965 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001966 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001967 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
1968 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001969 case Mips::SWM_MM:
1970 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001971 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
1972 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001973 case Mips::JalOneReg:
1974 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001975 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00001976 case Mips::BneImm:
1977 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001978 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00001979 case Mips::BLT:
1980 case Mips::BLE:
1981 case Mips::BGE:
1982 case Mips::BGT:
1983 case Mips::BLTU:
1984 case Mips::BLEU:
1985 case Mips::BGEU:
1986 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001987 case Mips::BLTL:
1988 case Mips::BLEL:
1989 case Mips::BGEL:
1990 case Mips::BGTL:
1991 case Mips::BLTUL:
1992 case Mips::BLEUL:
1993 case Mips::BGEUL:
1994 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00001995 case Mips::BLTImmMacro:
1996 case Mips::BLEImmMacro:
1997 case Mips::BGEImmMacro:
1998 case Mips::BGTImmMacro:
1999 case Mips::BLTUImmMacro:
2000 case Mips::BLEUImmMacro:
2001 case Mips::BGEUImmMacro:
2002 case Mips::BGTUImmMacro:
2003 case Mips::BLTLImmMacro:
2004 case Mips::BLELImmMacro:
2005 case Mips::BGELImmMacro:
2006 case Mips::BGTLImmMacro:
2007 case Mips::BLTULImmMacro:
2008 case Mips::BLEULImmMacro:
2009 case Mips::BGEULImmMacro:
2010 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002011 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002012 case Mips::SDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002013 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2014 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002015 case Mips::DSDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002016 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2017 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002018 case Mips::UDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002019 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2020 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002021 case Mips::DUDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002022 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2023 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002024 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002025 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2026 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002027 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002028 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002029 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002030 case Mips::PseudoTRUNC_W_D:
2031 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2032 : MER_Success;
2033 case Mips::Ulh:
2034 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2035 case Mips::Ulhu:
2036 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2037 case Mips::Ulw:
2038 return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2039 case Mips::NORImm:
2040 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002041 case Mips::ADDi:
2042 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002043 case Mips::SLTi:
2044 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002045 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2046 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2047 int64_t ImmValue = Inst.getOperand(2).getImm();
2048 if (isInt<16>(ImmValue))
2049 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002050 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2051 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002052 }
2053 return MER_NotAMacro;
2054 case Mips::ANDi:
2055 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002056 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002057 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2058 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2059 int64_t ImmValue = Inst.getOperand(2).getImm();
2060 if (isUInt<16>(ImmValue))
2061 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002062 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2063 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002064 }
2065 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002066 case Mips::ROL:
2067 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002068 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002069 case Mips::ROLImm:
2070 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002071 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002072 case Mips::DROL:
2073 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002074 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002075 case Mips::DROLImm:
2076 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002077 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002078 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002079 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002080 }
Jack Carter30a59822012-10-04 04:03:53 +00002081}
Jack Carter92995f12012-10-06 00:53:28 +00002082
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002083bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002084 MCStreamer &Out,
2085 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002086 MipsTargetStreamer &TOut = getTargetStreamer();
2087
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002088 // Create a JALR instruction which is going to replace the pseudo-JAL.
2089 MCInst JalrInst;
2090 JalrInst.setLoc(IDLoc);
2091 const MCOperand FirstRegOp = Inst.getOperand(0);
2092 const unsigned Opcode = Inst.getOpcode();
2093
2094 if (Opcode == Mips::JalOneReg) {
2095 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002096 if (IsCpRestoreSet && inMicroMipsMode()) {
2097 JalrInst.setOpcode(Mips::JALRS16_MM);
2098 JalrInst.addOperand(FirstRegOp);
2099 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002100 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002101 JalrInst.addOperand(FirstRegOp);
2102 } else {
2103 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002104 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002105 JalrInst.addOperand(FirstRegOp);
2106 }
2107 } else if (Opcode == Mips::JalTwoReg) {
2108 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002109 if (IsCpRestoreSet && inMicroMipsMode())
2110 JalrInst.setOpcode(Mips::JALRS_MM);
2111 else
2112 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002113 JalrInst.addOperand(FirstRegOp);
2114 const MCOperand SecondRegOp = Inst.getOperand(1);
2115 JalrInst.addOperand(SecondRegOp);
2116 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002117 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002118
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002119 // If .set reorder is active and branch instruction has a delay slot,
2120 // emit a NOP after it.
2121 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002122 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2123 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2124 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002125
2126 return false;
2127}
2128
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002129/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002130template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002131 unsigned BitNum = findFirstSet(x);
2132
2133 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2134}
2135
2136/// Load (or add) an immediate into a register.
2137///
2138/// @param ImmValue The immediate to load.
2139/// @param DstReg The register that will hold the immediate.
2140/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2141/// for a simple initialization.
2142/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2143/// @param IsAddress True if the immediate represents an address. False if it
2144/// is an integer.
2145/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002146bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002147 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002148 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2149 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002150 MipsTargetStreamer &TOut = getTargetStreamer();
2151
Toma Tabacu00e98672015-05-01 12:19:27 +00002152 if (!Is32BitImm && !isGP64bit()) {
2153 Error(IDLoc, "instruction requires a 64-bit architecture");
2154 return true;
2155 }
2156
Daniel Sanders03f9c012015-07-14 12:24:22 +00002157 if (Is32BitImm) {
2158 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2159 // Sign extend up to 64-bit so that the predicates match the hardware
2160 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2161 // true.
2162 ImmValue = SignExtend64<32>(ImmValue);
2163 } else {
2164 Error(IDLoc, "instruction requires a 32-bit immediate");
2165 return true;
2166 }
2167 }
2168
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002169 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2170 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2171
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002172 bool UseSrcReg = false;
2173 if (SrcReg != Mips::NoRegister)
2174 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002175
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002176 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002177 if (UseSrcReg &&
2178 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002179 // At this point we need AT to perform the expansions and we exit if it is
2180 // not available.
2181 unsigned ATReg = getATReg(IDLoc);
2182 if (!ATReg)
2183 return true;
2184 TmpReg = ATReg;
2185 }
2186
Daniel Sanders03f9c012015-07-14 12:24:22 +00002187 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002188 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002189 SrcReg = ZeroReg;
2190
2191 // This doesn't quite follow the usual ABI expectations for N32 but matches
2192 // traditional assembler behaviour. N32 would normally use addiu for both
2193 // integers and addresses.
2194 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002195 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002196 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002197 }
2198
Daniel Sandersa736b372016-04-29 13:33:12 +00002199 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002200 return false;
2201 }
2202
2203 if (isUInt<16>(ImmValue)) {
2204 unsigned TmpReg = DstReg;
2205 if (SrcReg == DstReg) {
2206 TmpReg = getATReg(IDLoc);
2207 if (!TmpReg)
2208 return true;
2209 }
2210
Daniel Sandersa736b372016-04-29 13:33:12 +00002211 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002212 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002213 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002214 return false;
2215 }
2216
2217 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002218 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002219
Toma Tabacu79588102015-04-29 10:19:56 +00002220 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2221 uint16_t Bits15To0 = ImmValue & 0xffff;
2222
Toma Tabacua3d056f2015-05-15 09:42:11 +00002223 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002224 // Traditional behaviour seems to special case this particular value. It's
2225 // not clear why other masks are handled differently.
2226 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002227 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2228 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002229 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002230 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002231 return false;
2232 }
2233
2234 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002235 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002236 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2237 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002238 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002239 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002240 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002241 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002242 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002243 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002244
Daniel Sandersa736b372016-04-29 13:33:12 +00002245 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002246 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002247 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002248 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002249 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002250 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002251 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002252
2253 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2254 if (Is32BitImm) {
2255 Error(IDLoc, "instruction requires a 32-bit immediate");
2256 return true;
2257 }
2258
2259 // Traditionally, these immediates are shifted as little as possible and as
2260 // such we align the most significant bit to bit 15 of our temporary.
2261 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2262 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2263 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2264 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002265 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2266 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002267
2268 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002269 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002270
2271 return false;
2272 }
2273
2274 warnIfNoMacro(IDLoc);
2275
2276 // The remaining case is packed with a sequence of dsll and ori with zeros
2277 // being omitted and any neighbouring dsll's being coalesced.
2278 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2279
2280 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2281 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002282 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002283 return false;
2284
2285 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2286 // skip it and defer the shift to the next chunk.
2287 unsigned ShiftCarriedForwards = 16;
2288 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2289 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2290
2291 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002292 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2293 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002294 ShiftCarriedForwards = 0;
2295 }
2296
2297 ShiftCarriedForwards += 16;
2298 }
2299 ShiftCarriedForwards -= 16;
2300
2301 // Finish any remaining shifts left by trailing zeros.
2302 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002303 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002304
2305 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002306 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002307
Matheus Almeida3813d572014-06-19 14:39:14 +00002308 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002309}
Jack Carter92995f12012-10-06 00:53:28 +00002310
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002311bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002312 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002313 const MCOperand &ImmOp = Inst.getOperand(1);
2314 assert(ImmOp.isImm() && "expected immediate operand kind");
2315 const MCOperand &DstRegOp = Inst.getOperand(0);
2316 assert(DstRegOp.isReg() && "expected register operand kind");
2317
2318 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002319 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002320 return true;
2321
2322 return false;
2323}
2324
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002325bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2326 const MCOperand &Offset,
2327 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002328 MCStreamer &Out,
2329 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002330 // la can't produce a usable address when addresses are 64-bit.
2331 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2332 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2333 // We currently can't do this because we depend on the equality
2334 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2335 Error(IDLoc, "la used to load 64-bit address");
2336 // Continue as if we had 'dla' instead.
2337 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002338 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002339
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002340 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002341 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002342 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002343 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002344 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002345
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002346 if (!Offset.isImm())
2347 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002348 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002349
Scott Egerton24557012016-01-21 15:11:01 +00002350 if (!ABI.ArePtrs64bit()) {
2351 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2352 Is32BitAddress = true;
2353 }
2354
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002355 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002356 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002357}
2358
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002359bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2360 unsigned DstReg, unsigned SrcReg,
2361 bool Is32BitSym, SMLoc IDLoc,
2362 MCStreamer &Out,
2363 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002364 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002365 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002366 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002367
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002368 if (inPicMode() && ABI.IsO32()) {
2369 MCValue Res;
2370 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2371 Error(IDLoc, "expected relocatable expression");
2372 return true;
2373 }
2374 if (Res.getSymB() != nullptr) {
2375 Error(IDLoc, "expected relocatable expression with only one symbol");
2376 return true;
2377 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002378
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002379 // The case where the result register is $25 is somewhat special. If the
2380 // symbol in the final relocation is external and not modified with a
2381 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2382 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2383 Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
2384 !Res.getSymA()->getSymbol().isTemporary()) {
2385 const MCExpr *CallExpr =
2386 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2387 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2388 MCOperand::createExpr(CallExpr), IDLoc, STI);
2389 return false;
2390 }
2391
2392 // The remaining cases are:
2393 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2394 // >addiu $tmp, $tmp, %lo(offset)
2395 // >addiu $rd, $tmp, $rs
2396 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2397 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2398 // >addiu $rd, $tmp, $rs
2399 // The addiu's marked with a '>' may be omitted if they are redundant. If
2400 // this happens then the last instruction must use $rd as the result
2401 // register.
2402 const MipsMCExpr *GotExpr =
2403 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2404 const MCExpr *LoExpr = nullptr;
2405 if (Res.getSymA()->getSymbol().isInSection() ||
2406 Res.getSymA()->getSymbol().isTemporary())
2407 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2408 else if (Res.getConstant() != 0) {
2409 // External symbols fully resolve the symbol with just the %got(symbol)
2410 // but we must still account for any offset to the symbol for expressions
2411 // like symbol+8.
2412 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2413 }
2414
2415 unsigned TmpReg = DstReg;
2416 if (UseSrcReg &&
2417 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2418 SrcReg)) {
2419 // If $rs is the same as $rd, we need to use AT.
2420 // If it is not available we exit.
2421 unsigned ATReg = getATReg(IDLoc);
2422 if (!ATReg)
2423 return true;
2424 TmpReg = ATReg;
2425 }
2426
2427 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2428 MCOperand::createExpr(GotExpr), IDLoc, STI);
2429
2430 if (LoExpr)
2431 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2432 IDLoc, STI);
2433
2434 if (UseSrcReg)
2435 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2436
2437 return false;
2438 }
2439
2440 const MipsMCExpr *HiExpr =
2441 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2442 const MipsMCExpr *LoExpr =
2443 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002444
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002445 // This is the 64-bit symbol address expansion.
2446 if (ABI.ArePtrs64bit() && isGP64bit()) {
2447 // We always need AT for the 64-bit expansion.
2448 // If it is not available we exit.
2449 unsigned ATReg = getATReg(IDLoc);
2450 if (!ATReg)
2451 return true;
2452
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002453 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002454 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002455 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002456 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002457
Scott Egerton24557012016-01-21 15:11:01 +00002458 if (UseSrcReg &&
2459 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2460 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002461 // If $rs is the same as $rd:
2462 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2463 // daddiu $at, $at, %higher(sym)
2464 // dsll $at, $at, 16
2465 // daddiu $at, $at, %hi(sym)
2466 // dsll $at, $at, 16
2467 // daddiu $at, $at, %lo(sym)
2468 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002469 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2470 STI);
2471 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2472 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2473 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2474 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2475 IDLoc, STI);
2476 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2477 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2478 IDLoc, STI);
2479 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002480
2481 return false;
2482 }
2483
2484 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2485 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2486 // lui $at, %hi(sym)
2487 // daddiu $rd, $rd, %higher(sym)
2488 // daddiu $at, $at, %lo(sym)
2489 // dsll32 $rd, $rd, 0
2490 // daddu $rd, $rd, $at
2491 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002492 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2493 STI);
2494 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2495 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2496 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2497 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2498 IDLoc, STI);
2499 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2500 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002501 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002502 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002503
2504 return false;
2505 }
2506
2507 // And now, the 32-bit symbol address expansion:
2508 // If $rs is the same as $rd:
2509 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2510 // ori $at, $at, %lo(sym)
2511 // addu $rd, $at, $rd
2512 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2513 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2514 // ori $rd, $rd, %lo(sym)
2515 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002516 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002517 if (UseSrcReg &&
2518 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002519 // If $rs is the same as $rd, we need to use AT.
2520 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002521 unsigned ATReg = getATReg(IDLoc);
2522 if (!ATReg)
2523 return true;
2524 TmpReg = ATReg;
2525 }
2526
Daniel Sandersa736b372016-04-29 13:33:12 +00002527 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2528 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2529 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002530
Toma Tabacufb9d1252015-06-22 12:08:39 +00002531 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002532 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002533 else
Scott Egerton24557012016-01-21 15:11:01 +00002534 assert(
2535 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002536
Toma Tabacu674825c2015-06-16 12:16:24 +00002537 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002538}
2539
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002540bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2541 MCStreamer &Out,
2542 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002543 MipsTargetStreamer &TOut = getTargetStreamer();
2544
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002545 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2546 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002547
2548 MCOperand Offset = Inst.getOperand(0);
2549 if (Offset.isExpr()) {
2550 Inst.clear();
2551 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002552 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2553 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2554 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002555 } else {
2556 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002557 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002558 // If offset fits into 11 bits then this instruction becomes microMIPS
2559 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002560 if (inMicroMipsMode())
2561 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002562 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002563 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002564 Error(IDLoc, "branch target out of range");
2565 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2566 Error(IDLoc, "branch to misaligned address");
2567 Inst.clear();
2568 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002569 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2570 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2571 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002572 }
2573 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002574 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002575
Zoran Jovanovicada70912015-09-07 11:56:37 +00002576 // If .set reorder is active and branch instruction has a delay slot,
2577 // emit a NOP after it.
2578 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2579 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002580 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002581
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002582 return false;
2583}
2584
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002585bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2586 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002587 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002588 const MCOperand &DstRegOp = Inst.getOperand(0);
2589 assert(DstRegOp.isReg() && "expected register operand kind");
2590
2591 const MCOperand &ImmOp = Inst.getOperand(1);
2592 assert(ImmOp.isImm() && "expected immediate operand kind");
2593
2594 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002595 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2596 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002597
2598 unsigned OpCode = 0;
2599 switch(Inst.getOpcode()) {
2600 case Mips::BneImm:
2601 OpCode = Mips::BNE;
2602 break;
2603 case Mips::BeqImm:
2604 OpCode = Mips::BEQ;
2605 break;
2606 default:
2607 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2608 break;
2609 }
2610
2611 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002612 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002613 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2614 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002615 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002616 warnIfNoMacro(IDLoc);
2617
2618 unsigned ATReg = getATReg(IDLoc);
2619 if (!ATReg)
2620 return true;
2621
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002622 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002623 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002624 return true;
2625
Daniel Sandersa736b372016-04-29 13:33:12 +00002626 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002627 }
2628 return false;
2629}
2630
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002631void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002632 const MCSubtargetInfo *STI, bool IsLoad,
2633 bool IsImmOpnd) {
2634 if (IsLoad) {
2635 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2636 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002637 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002638 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2639}
2640
2641void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2642 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2643 MipsTargetStreamer &TOut = getTargetStreamer();
2644
2645 unsigned DstReg = Inst.getOperand(0).getReg();
2646 unsigned BaseReg = Inst.getOperand(1).getReg();
2647
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002648 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002649 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2650 unsigned DstRegClassID =
2651 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2652 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2653 (DstRegClassID == Mips::GPR64RegClassID);
2654
2655 if (IsImmOpnd) {
2656 // Try to use DstReg as the temporary.
2657 if (IsGPR && (BaseReg != DstReg)) {
2658 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2659 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2660 STI);
2661 return;
2662 }
2663
Matheus Almeida7de68e72014-06-18 14:46:05 +00002664 // At this point we need AT to perform the expansions and we exit if it is
2665 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002666 unsigned ATReg = getATReg(IDLoc);
2667 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002668 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002669
2670 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2671 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2672 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002673 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002674
Daniel Sandersfba875f2016-04-29 13:43:45 +00002675 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002676 MCOperand LoOperand = MCOperand::createExpr(
2677 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2678 MCOperand HiOperand = MCOperand::createExpr(
2679 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002680
2681 // Try to use DstReg as the temporary.
2682 if (IsGPR && (BaseReg != DstReg)) {
2683 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2684 LoOperand, DstReg, IDLoc, STI);
2685 return;
2686 }
2687
2688 // At this point we need AT to perform the expansions and we exit if it is
2689 // not available.
2690 unsigned ATReg = getATReg(IDLoc);
2691 if (!ATReg)
2692 return;
2693
2694 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2695 LoOperand, ATReg, IDLoc, STI);
2696}
2697
2698void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2699 const MCSubtargetInfo *STI,
2700 bool IsImmOpnd) {
2701 MipsTargetStreamer &TOut = getTargetStreamer();
2702
2703 unsigned SrcReg = Inst.getOperand(0).getReg();
2704 unsigned BaseReg = Inst.getOperand(1).getReg();
2705
Daniel Sanders241c6792016-05-12 14:01:50 +00002706 if (IsImmOpnd) {
2707 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2708 Inst.getOperand(2).getImm(),
2709 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
2710 return;
2711 }
2712
Daniel Sandersfba875f2016-04-29 13:43:45 +00002713 unsigned ATReg = getATReg(IDLoc);
2714 if (!ATReg)
2715 return;
2716
Daniel Sandersfba875f2016-04-29 13:43:45 +00002717 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002718 MCOperand LoOperand = MCOperand::createExpr(
2719 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2720 MCOperand HiOperand = MCOperand::createExpr(
2721 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002722 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2723 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002724}
2725
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002726bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2727 MCStreamer &Out,
2728 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002729 unsigned OpNum = Inst.getNumOperands();
2730 unsigned Opcode = Inst.getOpcode();
2731 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2732
2733 assert (Inst.getOperand(OpNum - 1).isImm() &&
2734 Inst.getOperand(OpNum - 2).isReg() &&
2735 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2736
2737 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2738 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002739 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2740 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2741 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2742 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002743 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002744 if (inMicroMipsMode() && hasMips32r6())
2745 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2746 else
2747 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2748 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002749
2750 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002751 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002752 return false;
2753}
2754
Toma Tabacu1a108322015-06-17 13:20:24 +00002755bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002756 MCStreamer &Out,
2757 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002758 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002759 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002760 unsigned PseudoOpcode = Inst.getOpcode();
2761 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002762 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002763 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2764
2765 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002766 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002767
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002768 unsigned TrgReg;
2769 if (TrgOp.isReg())
2770 TrgReg = TrgOp.getReg();
2771 else if (TrgOp.isImm()) {
2772 warnIfNoMacro(IDLoc);
2773 EmittedNoMacroWarning = true;
2774
2775 TrgReg = getATReg(IDLoc);
2776 if (!TrgReg)
2777 return true;
2778
2779 switch(PseudoOpcode) {
2780 default:
2781 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2782 case Mips::BLTImmMacro:
2783 PseudoOpcode = Mips::BLT;
2784 break;
2785 case Mips::BLEImmMacro:
2786 PseudoOpcode = Mips::BLE;
2787 break;
2788 case Mips::BGEImmMacro:
2789 PseudoOpcode = Mips::BGE;
2790 break;
2791 case Mips::BGTImmMacro:
2792 PseudoOpcode = Mips::BGT;
2793 break;
2794 case Mips::BLTUImmMacro:
2795 PseudoOpcode = Mips::BLTU;
2796 break;
2797 case Mips::BLEUImmMacro:
2798 PseudoOpcode = Mips::BLEU;
2799 break;
2800 case Mips::BGEUImmMacro:
2801 PseudoOpcode = Mips::BGEU;
2802 break;
2803 case Mips::BGTUImmMacro:
2804 PseudoOpcode = Mips::BGTU;
2805 break;
2806 case Mips::BLTLImmMacro:
2807 PseudoOpcode = Mips::BLTL;
2808 break;
2809 case Mips::BLELImmMacro:
2810 PseudoOpcode = Mips::BLEL;
2811 break;
2812 case Mips::BGELImmMacro:
2813 PseudoOpcode = Mips::BGEL;
2814 break;
2815 case Mips::BGTLImmMacro:
2816 PseudoOpcode = Mips::BGTL;
2817 break;
2818 case Mips::BLTULImmMacro:
2819 PseudoOpcode = Mips::BLTUL;
2820 break;
2821 case Mips::BLEULImmMacro:
2822 PseudoOpcode = Mips::BLEUL;
2823 break;
2824 case Mips::BGEULImmMacro:
2825 PseudoOpcode = Mips::BGEUL;
2826 break;
2827 case Mips::BGTULImmMacro:
2828 PseudoOpcode = Mips::BGTUL;
2829 break;
2830 }
2831
2832 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002833 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002834 return true;
2835 }
2836
Toma Tabacu1a108322015-06-17 13:20:24 +00002837 switch (PseudoOpcode) {
2838 case Mips::BLT:
2839 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002840 case Mips::BLTL:
2841 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002842 AcceptsEquality = false;
2843 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002844 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2845 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002846 ZeroSrcOpcode = Mips::BGTZ;
2847 ZeroTrgOpcode = Mips::BLTZ;
2848 break;
2849 case Mips::BLE:
2850 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002851 case Mips::BLEL:
2852 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002853 AcceptsEquality = true;
2854 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002855 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2856 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002857 ZeroSrcOpcode = Mips::BGEZ;
2858 ZeroTrgOpcode = Mips::BLEZ;
2859 break;
2860 case Mips::BGE:
2861 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002862 case Mips::BGEL:
2863 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002864 AcceptsEquality = true;
2865 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002866 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2867 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002868 ZeroSrcOpcode = Mips::BLEZ;
2869 ZeroTrgOpcode = Mips::BGEZ;
2870 break;
2871 case Mips::BGT:
2872 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002873 case Mips::BGTL:
2874 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002875 AcceptsEquality = false;
2876 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002877 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2878 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002879 ZeroSrcOpcode = Mips::BLTZ;
2880 ZeroTrgOpcode = Mips::BGTZ;
2881 break;
2882 default:
2883 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2884 }
2885
Toma Tabacu1a108322015-06-17 13:20:24 +00002886 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2887 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2888 if (IsSrcRegZero && IsTrgRegZero) {
2889 // FIXME: All of these Opcode-specific if's are needed for compatibility
2890 // with GAS' behaviour. However, they may not generate the most efficient
2891 // code in some circumstances.
2892 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002893 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2894 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002895 return false;
2896 }
2897 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002898 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2899 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002900 Warning(IDLoc, "branch is always taken");
2901 return false;
2902 }
2903 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002904 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2905 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002906 Warning(IDLoc, "branch is always taken");
2907 return false;
2908 }
2909 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002910 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2911 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002912 return false;
2913 }
2914 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002915 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2916 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002917 return false;
2918 }
2919 if (AcceptsEquality) {
2920 // If both registers are $0 and the pseudo-branch accepts equality, it
2921 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00002922 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2923 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002924 Warning(IDLoc, "branch is always taken");
2925 return false;
2926 }
2927 // If both registers are $0 and the pseudo-branch does not accept
2928 // equality, it will never be taken, so we don't have to emit anything.
2929 return false;
2930 }
2931 if (IsSrcRegZero || IsTrgRegZero) {
2932 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2933 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2934 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2935 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2936 // the pseudo-branch will never be taken, so we don't emit anything.
2937 // This only applies to unsigned pseudo-branches.
2938 return false;
2939 }
2940 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2941 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2942 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2943 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2944 // the pseudo-branch will always be taken, so we emit an unconditional
2945 // branch.
2946 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00002947 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2948 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002949 Warning(IDLoc, "branch is always taken");
2950 return false;
2951 }
2952 if (IsUnsigned) {
2953 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2954 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2955 // the pseudo-branch will be taken only when the non-zero register is
2956 // different from 0, so we emit a BNEZ.
2957 //
2958 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2959 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2960 // the pseudo-branch will be taken only when the non-zero register is
2961 // equal to 0, so we emit a BEQZ.
2962 //
2963 // Because only BLEU and BGEU branch on equality, we can use the
2964 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00002965 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2966 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2967 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002968 return false;
2969 }
2970 // If we have a signed pseudo-branch and one of the registers is $0,
2971 // we can use an appropriate compare-to-zero branch. We select which one
2972 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00002973 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2974 IsSrcRegZero ? TrgReg : SrcReg,
2975 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002976 return false;
2977 }
2978
2979 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2980 // expansions. If it is not available, we return.
2981 unsigned ATRegNum = getATReg(IDLoc);
2982 if (!ATRegNum)
2983 return true;
2984
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002985 if (!EmittedNoMacroWarning)
2986 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002987
2988 // SLT fits well with 2 of our 4 pseudo-branches:
2989 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2990 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2991 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2992 // This is accomplished by using a BNEZ with the result of the SLT.
2993 //
2994 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2995 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2996 // Because only BGE and BLE branch on equality, we can use the
2997 // AcceptsEquality variable to decide when to emit the BEQZ.
2998 // Note that the order of the SLT arguments doesn't change between
2999 // opposites.
3000 //
3001 // The same applies to the unsigned variants, except that SLTu is used
3002 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003003 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3004 ReverseOrderSLT ? TrgReg : SrcReg,
3005 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003006
Daniel Sandersa736b372016-04-29 13:33:12 +00003007 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3008 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3009 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3010 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003011 return false;
3012}
3013
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003014bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3015 const MCSubtargetInfo *STI, const bool IsMips64,
3016 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003017 MipsTargetStreamer &TOut = getTargetStreamer();
3018
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003019 warnIfNoMacro(IDLoc);
3020
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003021 const MCOperand &RdRegOp = Inst.getOperand(0);
3022 assert(RdRegOp.isReg() && "expected register operand kind");
3023 unsigned RdReg = RdRegOp.getReg();
3024
3025 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003026 assert(RsRegOp.isReg() && "expected register operand kind");
3027 unsigned RsReg = RsRegOp.getReg();
3028
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003029 const MCOperand &RtRegOp = Inst.getOperand(2);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003030 assert(RtRegOp.isReg() && "expected register operand kind");
3031 unsigned RtReg = RtRegOp.getReg();
3032 unsigned DivOp;
3033 unsigned ZeroReg;
3034
3035 if (IsMips64) {
3036 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3037 ZeroReg = Mips::ZERO_64;
3038 } else {
3039 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3040 ZeroReg = Mips::ZERO;
3041 }
3042
3043 bool UseTraps = useTraps();
3044
3045 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
3046 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
3047 Warning(IDLoc, "dividing zero by zero");
3048 if (IsMips64) {
3049 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
3050 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003051 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003052 return false;
3053 }
3054
Daniel Sandersa736b372016-04-29 13:33:12 +00003055 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003056 return false;
3057 }
3058 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00003059 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003060 return false;
3061 }
3062 }
3063
3064 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3065 Warning(IDLoc, "division by zero");
3066 if (Signed) {
3067 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003068 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003069 return false;
3070 }
3071
Daniel Sandersa736b372016-04-29 13:33:12 +00003072 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003073 return false;
3074 }
3075 }
3076
3077 // FIXME: The values for these two BranchTarget variables may be different in
3078 // micromips. These magic numbers need to be removed.
3079 unsigned BranchTargetNoTraps;
3080 unsigned BranchTarget;
3081
3082 if (UseTraps) {
3083 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003084 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003085 } else {
3086 BranchTarget = IsMips64 ? 20 : 16;
3087 BranchTargetNoTraps = 8;
3088 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003089 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003090 }
3091
Daniel Sandersa736b372016-04-29 13:33:12 +00003092 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003093
3094 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003095 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003096
3097 if (!Signed) {
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003098 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003099 return false;
3100 }
3101
3102 unsigned ATReg = getATReg(IDLoc);
3103 if (!ATReg)
3104 return true;
3105
Daniel Sandersa736b372016-04-29 13:33:12 +00003106 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003107 if (IsMips64) {
3108 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003109 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3110 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3111 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003112 } else {
3113 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003114 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3115 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003116 }
3117
3118 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003119 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003120 else {
3121 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003122 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3123 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3124 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003125 }
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003126 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003127 return false;
3128}
3129
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003130bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003131 SMLoc IDLoc, MCStreamer &Out,
3132 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003133 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003134
3135 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3136 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3137 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3138
3139 unsigned FirstReg = Inst.getOperand(0).getReg();
3140 unsigned SecondReg = Inst.getOperand(1).getReg();
3141 unsigned ThirdReg = Inst.getOperand(2).getReg();
3142
3143 if (hasMips1() && !hasMips2()) {
3144 unsigned ATReg = getATReg(IDLoc);
3145 if (!ATReg)
3146 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003147 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3148 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3149 TOut.emitNop(IDLoc, STI);
3150 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3151 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3152 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3153 TOut.emitNop(IDLoc, STI);
3154 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3155 : Mips::CVT_W_S,
3156 FirstReg, SecondReg, IDLoc, STI);
3157 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3158 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003159 return false;
3160 }
3161
Daniel Sandersa736b372016-04-29 13:33:12 +00003162 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3163 : Mips::TRUNC_W_S,
3164 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003165
3166 return false;
3167}
3168
Daniel Sanders6394ee52015-10-15 14:52:58 +00003169bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003170 MCStreamer &Out, const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003171 MipsTargetStreamer &TOut = getTargetStreamer();
3172
Toma Tabacud88d79c2015-06-23 14:39:42 +00003173 if (hasMips32r6() || hasMips64r6()) {
3174 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3175 return false;
3176 }
3177
3178 warnIfNoMacro(IDLoc);
3179
3180 const MCOperand &DstRegOp = Inst.getOperand(0);
3181 assert(DstRegOp.isReg() && "expected register operand kind");
3182
3183 const MCOperand &SrcRegOp = Inst.getOperand(1);
3184 assert(SrcRegOp.isReg() && "expected register operand kind");
3185
3186 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3187 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3188
3189 unsigned DstReg = DstRegOp.getReg();
3190 unsigned SrcReg = SrcRegOp.getReg();
3191 int64_t OffsetValue = OffsetImmOp.getImm();
3192
3193 // NOTE: We always need AT for ULHU, as it is always used as the source
3194 // register for one of the LBu's.
3195 unsigned ATReg = getATReg(IDLoc);
3196 if (!ATReg)
3197 return true;
3198
3199 // When the value of offset+1 does not fit in 16 bits, we have to load the
3200 // offset in AT, (D)ADDu the original source register (if there was one), and
3201 // then use AT as the source register for the 2 generated LBu's.
3202 bool LoadedOffsetInAT = false;
3203 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3204 LoadedOffsetInAT = true;
3205
3206 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003207 true, IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003208 return true;
3209
3210 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3211 // because it will make our output more similar to GAS'. For example,
3212 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3213 // instead of just an "ori $1, $9, 32768".
3214 // NOTE: If there is no source register specified in the ULHU, the parser
3215 // will interpret it as $0.
3216 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003217 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003218 }
3219
3220 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3221 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3222 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3223
3224 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3225 if (isLittle()) {
3226 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3227 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3228 } else {
3229 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3230 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3231 }
3232
3233 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3234
Daniel Sandersa736b372016-04-29 13:33:12 +00003235 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3236 FirstLbuOffset, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003237
Daniel Sandersa736b372016-04-29 13:33:12 +00003238 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3239 STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003240
Daniel Sandersa736b372016-04-29 13:33:12 +00003241 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003242
Daniel Sandersa736b372016-04-29 13:33:12 +00003243 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003244
3245 return false;
3246}
3247
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003248bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3249 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003250 MipsTargetStreamer &TOut = getTargetStreamer();
3251
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003252 if (hasMips32r6() || hasMips64r6()) {
3253 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3254 return false;
3255 }
3256
3257 const MCOperand &DstRegOp = Inst.getOperand(0);
3258 assert(DstRegOp.isReg() && "expected register operand kind");
3259
3260 const MCOperand &SrcRegOp = Inst.getOperand(1);
3261 assert(SrcRegOp.isReg() && "expected register operand kind");
3262
3263 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3264 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3265
3266 unsigned SrcReg = SrcRegOp.getReg();
3267 int64_t OffsetValue = OffsetImmOp.getImm();
3268 unsigned ATReg = 0;
3269
3270 // When the value of offset+3 does not fit in 16 bits, we have to load the
3271 // offset in AT, (D)ADDu the original source register (if there was one), and
3272 // then use AT as the source register for the generated LWL and LWR.
3273 bool LoadedOffsetInAT = false;
3274 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3275 ATReg = getATReg(IDLoc);
3276 if (!ATReg)
3277 return true;
3278 LoadedOffsetInAT = true;
3279
3280 warnIfNoMacro(IDLoc);
3281
3282 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003283 true, IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003284 return true;
3285
3286 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3287 // because it will make our output more similar to GAS'. For example,
3288 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3289 // instead of just an "ori $1, $9, 32768".
3290 // NOTE: If there is no source register specified in the ULW, the parser
3291 // will interpret it as $0.
3292 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003293 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003294 }
3295
3296 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3297 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3298 if (isLittle()) {
3299 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3300 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3301 } else {
3302 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3303 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3304 }
3305
Daniel Sandersa736b372016-04-29 13:33:12 +00003306 TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3307 STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003308
Daniel Sandersa736b372016-04-29 13:33:12 +00003309 TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
3310 IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003311
3312 return false;
3313}
3314
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003315bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003316 MCStreamer &Out,
3317 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003318 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003319
3320 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3321 assert (Inst.getOperand(0).isReg() &&
3322 Inst.getOperand(1).isReg() &&
3323 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3324
3325 unsigned ATReg = Mips::NoRegister;
3326 unsigned FinalDstReg = Mips::NoRegister;
3327 unsigned DstReg = Inst.getOperand(0).getReg();
3328 unsigned SrcReg = Inst.getOperand(1).getReg();
3329 int64_t ImmValue = Inst.getOperand(2).getImm();
3330
3331 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3332
3333 unsigned FinalOpcode = Inst.getOpcode();
3334
3335 if (DstReg == SrcReg) {
3336 ATReg = getATReg(Inst.getLoc());
3337 if (!ATReg)
3338 return true;
3339 FinalDstReg = DstReg;
3340 DstReg = ATReg;
3341 }
3342
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003343 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003344 switch (FinalOpcode) {
3345 default:
3346 llvm_unreachable("unimplemented expansion");
3347 case (Mips::ADDi):
3348 FinalOpcode = Mips::ADD;
3349 break;
3350 case (Mips::ADDiu):
3351 FinalOpcode = Mips::ADDu;
3352 break;
3353 case (Mips::ANDi):
3354 FinalOpcode = Mips::AND;
3355 break;
3356 case (Mips::NORImm):
3357 FinalOpcode = Mips::NOR;
3358 break;
3359 case (Mips::ORi):
3360 FinalOpcode = Mips::OR;
3361 break;
3362 case (Mips::SLTi):
3363 FinalOpcode = Mips::SLT;
3364 break;
3365 case (Mips::SLTiu):
3366 FinalOpcode = Mips::SLTu;
3367 break;
3368 case (Mips::XORi):
3369 FinalOpcode = Mips::XOR;
3370 break;
3371 }
3372
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003373 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003374 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003375 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003376 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003377 return false;
3378 }
3379 return true;
3380}
3381
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003382bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3383 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003384 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003385 unsigned ATReg = Mips::NoRegister;
3386 unsigned DReg = Inst.getOperand(0).getReg();
3387 unsigned SReg = Inst.getOperand(1).getReg();
3388 unsigned TReg = Inst.getOperand(2).getReg();
3389 unsigned TmpReg = DReg;
3390
3391 unsigned FirstShift = Mips::NOP;
3392 unsigned SecondShift = Mips::NOP;
3393
3394 if (hasMips32r2()) {
3395
3396 if (DReg == SReg) {
3397 TmpReg = getATReg(Inst.getLoc());
3398 if (!TmpReg)
3399 return true;
3400 }
3401
3402 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003403 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3404 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003405 return false;
3406 }
3407
3408 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003409 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003410 return false;
3411 }
3412
3413 return true;
3414 }
3415
3416 if (hasMips32()) {
3417
3418 switch (Inst.getOpcode()) {
3419 default:
3420 llvm_unreachable("unexpected instruction opcode");
3421 case Mips::ROL:
3422 FirstShift = Mips::SRLV;
3423 SecondShift = Mips::SLLV;
3424 break;
3425 case Mips::ROR:
3426 FirstShift = Mips::SLLV;
3427 SecondShift = Mips::SRLV;
3428 break;
3429 }
3430
3431 ATReg = getATReg(Inst.getLoc());
3432 if (!ATReg)
3433 return true;
3434
Daniel Sandersa736b372016-04-29 13:33:12 +00003435 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3436 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3437 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3438 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003439
3440 return false;
3441 }
3442
3443 return true;
3444}
3445
3446bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003447 MCStreamer &Out,
3448 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003449 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003450 unsigned ATReg = Mips::NoRegister;
3451 unsigned DReg = Inst.getOperand(0).getReg();
3452 unsigned SReg = Inst.getOperand(1).getReg();
3453 int64_t ImmValue = Inst.getOperand(2).getImm();
3454
3455 unsigned FirstShift = Mips::NOP;
3456 unsigned SecondShift = Mips::NOP;
3457
3458 if (hasMips32r2()) {
3459
3460 if (Inst.getOpcode() == Mips::ROLImm) {
3461 uint64_t MaxShift = 32;
3462 uint64_t ShiftValue = ImmValue;
3463 if (ImmValue != 0)
3464 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003465 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003466 return false;
3467 }
3468
3469 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003470 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003471 return false;
3472 }
3473
3474 return true;
3475 }
3476
3477 if (hasMips32()) {
3478
3479 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003480 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003481 return false;
3482 }
3483
3484 switch (Inst.getOpcode()) {
3485 default:
3486 llvm_unreachable("unexpected instruction opcode");
3487 case Mips::ROLImm:
3488 FirstShift = Mips::SLL;
3489 SecondShift = Mips::SRL;
3490 break;
3491 case Mips::RORImm:
3492 FirstShift = Mips::SRL;
3493 SecondShift = Mips::SLL;
3494 break;
3495 }
3496
3497 ATReg = getATReg(Inst.getLoc());
3498 if (!ATReg)
3499 return true;
3500
Daniel Sandersa736b372016-04-29 13:33:12 +00003501 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3502 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3503 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003504
3505 return false;
3506 }
3507
3508 return true;
3509}
3510
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003511bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3512 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003513 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003514 unsigned ATReg = Mips::NoRegister;
3515 unsigned DReg = Inst.getOperand(0).getReg();
3516 unsigned SReg = Inst.getOperand(1).getReg();
3517 unsigned TReg = Inst.getOperand(2).getReg();
3518 unsigned TmpReg = DReg;
3519
3520 unsigned FirstShift = Mips::NOP;
3521 unsigned SecondShift = Mips::NOP;
3522
3523 if (hasMips64r2()) {
3524
3525 if (TmpReg == SReg) {
3526 TmpReg = getATReg(Inst.getLoc());
3527 if (!TmpReg)
3528 return true;
3529 }
3530
3531 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003532 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3533 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003534 return false;
3535 }
3536
3537 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003538 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003539 return false;
3540 }
3541
3542 return true;
3543 }
3544
3545 if (hasMips64()) {
3546
3547 switch (Inst.getOpcode()) {
3548 default:
3549 llvm_unreachable("unexpected instruction opcode");
3550 case Mips::DROL:
3551 FirstShift = Mips::DSRLV;
3552 SecondShift = Mips::DSLLV;
3553 break;
3554 case Mips::DROR:
3555 FirstShift = Mips::DSLLV;
3556 SecondShift = Mips::DSRLV;
3557 break;
3558 }
3559
3560 ATReg = getATReg(Inst.getLoc());
3561 if (!ATReg)
3562 return true;
3563
Daniel Sandersa736b372016-04-29 13:33:12 +00003564 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3565 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3566 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3567 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003568
3569 return false;
3570 }
3571
3572 return true;
3573}
3574
3575bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003576 MCStreamer &Out,
3577 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003578 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003579 unsigned ATReg = Mips::NoRegister;
3580 unsigned DReg = Inst.getOperand(0).getReg();
3581 unsigned SReg = Inst.getOperand(1).getReg();
3582 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3583
3584 unsigned FirstShift = Mips::NOP;
3585 unsigned SecondShift = Mips::NOP;
3586
3587 MCInst TmpInst;
3588
3589 if (hasMips64r2()) {
3590
3591 unsigned FinalOpcode = Mips::NOP;
3592 if (ImmValue == 0)
3593 FinalOpcode = Mips::DROTR;
3594 else if (ImmValue % 32 == 0)
3595 FinalOpcode = Mips::DROTR32;
3596 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3597 if (Inst.getOpcode() == Mips::DROLImm)
3598 FinalOpcode = Mips::DROTR32;
3599 else
3600 FinalOpcode = Mips::DROTR;
3601 } else if (ImmValue >= 33) {
3602 if (Inst.getOpcode() == Mips::DROLImm)
3603 FinalOpcode = Mips::DROTR;
3604 else
3605 FinalOpcode = Mips::DROTR32;
3606 }
3607
3608 uint64_t ShiftValue = ImmValue % 32;
3609 if (Inst.getOpcode() == Mips::DROLImm)
3610 ShiftValue = (32 - ImmValue % 32) % 32;
3611
Daniel Sandersa736b372016-04-29 13:33:12 +00003612 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003613
3614 return false;
3615 }
3616
3617 if (hasMips64()) {
3618
3619 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003620 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003621 return false;
3622 }
3623
3624 switch (Inst.getOpcode()) {
3625 default:
3626 llvm_unreachable("unexpected instruction opcode");
3627 case Mips::DROLImm:
3628 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3629 FirstShift = Mips::DSLL;
3630 SecondShift = Mips::DSRL32;
3631 }
3632 if (ImmValue == 32) {
3633 FirstShift = Mips::DSLL32;
3634 SecondShift = Mips::DSRL32;
3635 }
3636 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3637 FirstShift = Mips::DSLL32;
3638 SecondShift = Mips::DSRL;
3639 }
3640 break;
3641 case Mips::DRORImm:
3642 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3643 FirstShift = Mips::DSRL;
3644 SecondShift = Mips::DSLL32;
3645 }
3646 if (ImmValue == 32) {
3647 FirstShift = Mips::DSRL32;
3648 SecondShift = Mips::DSLL32;
3649 }
3650 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3651 FirstShift = Mips::DSRL32;
3652 SecondShift = Mips::DSLL;
3653 }
3654 break;
3655 }
3656
3657 ATReg = getATReg(Inst.getLoc());
3658 if (!ATReg)
3659 return true;
3660
Daniel Sandersa736b372016-04-29 13:33:12 +00003661 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3662 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3663 Inst.getLoc(), STI);
3664 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003665
3666 return false;
3667 }
3668
3669 return true;
3670}
3671
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003672bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3673 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003674 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003675 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3676 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3677
Daniel Sandersa736b372016-04-29 13:33:12 +00003678 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003679 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003680 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003681 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003682 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3683 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003684
3685 return false;
3686}
3687
Matheus Almeida595fcab2014-06-11 15:05:56 +00003688unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00003689 switch (Inst.getOpcode()) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003690 // As described by the Mips32r2 spec, the registers Rd and Rs for
3691 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00003692 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00003693 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00003694 case Mips::JALR_HB:
3695 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00003696 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00003697 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
3698 return Match_RequiresDifferentSrcAndDst;
3699 return Match_Success;
3700 case Mips::LWP_MM:
3701 case Mips::LWP_MMR6:
3702 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
3703 return Match_RequiresDifferentSrcAndDst;
3704 return Match_Success;
3705 // As described the MIPSR6 spec, the compact branches that compare registers
3706 // must:
3707 // a) Not use the zero register.
3708 // b) Not use the same register twice.
3709 // c) rs < rt for bnec, beqc.
3710 // NB: For this case, the encoding will swap the operands as their
3711 // ordering doesn't matter. GAS performs this transformation too.
3712 // Hence, that constraint does not have to be enforced.
3713 //
3714 // The compact branches that branch iff the signed addition of two registers
3715 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
3716 // operand swapping. They do not have restriction of using the zero register.
3717 case Mips::BLEZC:
3718 case Mips::BGEZC:
3719 case Mips::BGTZC:
3720 case Mips::BLTZC:
3721 case Mips::BEQZC:
3722 case Mips::BNEZC:
3723 if (Inst.getOperand(0).getReg() == Mips::ZERO)
3724 return Match_RequiresNoZeroRegister;
3725 return Match_Success;
3726 case Mips::BGEC:
3727 case Mips::BLTC:
3728 case Mips::BGEUC:
3729 case Mips::BLTUC:
3730 case Mips::BEQC:
3731 case Mips::BNEC:
3732 if (Inst.getOperand(0).getReg() == Mips::ZERO)
3733 return Match_RequiresNoZeroRegister;
3734 if (Inst.getOperand(1).getReg() == Mips::ZERO)
3735 return Match_RequiresNoZeroRegister;
3736 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
3737 return Match_RequiresDifferentOperands;
3738 return Match_Success;
3739 default:
3740 return Match_Success;
3741 }
Matheus Almeida595fcab2014-06-11 15:05:56 +00003742}
3743
Daniel Sanders52da7af2015-11-06 12:11:03 +00003744static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3745 uint64_t ErrorInfo) {
3746 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3747 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3748 if (ErrorLoc == SMLoc())
3749 return Loc;
3750 return ErrorLoc;
3751 }
3752 return Loc;
3753}
3754
David Blaikie960ea3f2014-06-08 16:18:35 +00003755bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3756 OperandVector &Operands,
3757 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003758 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003759 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003760
Jack Carterb4dbc172012-09-05 23:34:03 +00003761 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00003762 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003763 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003764
3765 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003766 case Match_Success: {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003767 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00003768 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003769 return false;
3770 }
3771 case Match_MissingFeature:
3772 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3773 return true;
3774 case Match_InvalidOperand: {
3775 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003776 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003777 if (ErrorInfo >= Operands.size())
3778 return Error(IDLoc, "too few operands for instruction");
3779
Daniel Sanders52da7af2015-11-06 12:11:03 +00003780 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003781 if (ErrorLoc == SMLoc())
3782 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003783 }
3784
3785 return Error(ErrorLoc, "invalid operand for instruction");
3786 }
3787 case Match_MnemonicFail:
3788 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003789 case Match_RequiresDifferentSrcAndDst:
3790 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00003791 case Match_RequiresDifferentOperands:
3792 return Error(IDLoc, "registers must be different");
3793 case Match_RequiresNoZeroRegister:
3794 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003795 case Match_Immz:
3796 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003797 case Match_UImm1_0:
3798 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3799 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003800 case Match_UImm2_0:
3801 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3802 "expected 2-bit unsigned immediate");
3803 case Match_UImm2_1:
3804 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3805 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003806 case Match_UImm3_0:
3807 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3808 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003809 case Match_UImm4_0:
3810 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3811 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003812 case Match_SImm4_0:
3813 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3814 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003815 case Match_UImm5_0:
3816 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3817 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00003818 case Match_SImm5_0:
3819 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3820 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003821 case Match_UImm5_1:
3822 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3823 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003824 case Match_UImm5_32:
3825 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3826 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003827 case Match_UImm5_33:
3828 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3829 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003830 case Match_UImm5_0_Report_UImm6:
3831 // This is used on UImm5 operands that have a corresponding UImm5_32
3832 // operand to avoid confusing the user.
3833 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3834 "expected 6-bit unsigned immediate");
3835 case Match_UImm5_Lsl2:
3836 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3837 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003838 case Match_UImmRange2_64:
3839 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3840 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003841 case Match_UImm6_0:
3842 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3843 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00003844 case Match_UImm6_Lsl2:
3845 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3846 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00003847 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00003848 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3849 "expected 6-bit signed immediate");
3850 case Match_UImm7_0:
3851 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3852 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00003853 case Match_UImm7_N1:
3854 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3855 "expected immediate in range -1 .. 126");
3856 case Match_SImm7_Lsl2:
3857 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3858 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003859 case Match_UImm8_0:
3860 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3861 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003862 case Match_UImm10_0:
3863 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3864 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00003865 case Match_SImm10_0:
3866 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3867 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00003868 case Match_SImm11_0:
3869 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3870 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003871 case Match_UImm16:
3872 case Match_UImm16_Relaxed:
3873 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3874 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003875 case Match_SImm16:
3876 case Match_SImm16_Relaxed:
3877 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3878 "expected 16-bit signed immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003879 case Match_UImm20_0:
3880 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3881 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00003882 case Match_UImm26_0:
3883 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3884 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00003885 case Match_SImm32:
3886 case Match_SImm32_Relaxed:
3887 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3888 "expected 32-bit signed immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00003889 case Match_MemSImm9:
3890 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3891 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00003892 case Match_MemSImm10:
3893 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3894 "expected memory with 10-bit signed offset");
3895 case Match_MemSImm10Lsl1:
3896 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3897 "expected memory with 11-bit signed offset and multiple of 2");
3898 case Match_MemSImm10Lsl2:
3899 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3900 "expected memory with 12-bit signed offset and multiple of 4");
3901 case Match_MemSImm10Lsl3:
3902 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3903 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00003904 case Match_MemSImm11:
3905 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3906 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00003907 case Match_MemSImm12:
3908 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3909 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003910 case Match_MemSImm16:
3911 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3912 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00003913 }
Craig Topper589ceee2015-01-03 08:16:34 +00003914
3915 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003916}
3917
Toma Tabacud9d344b2015-04-27 14:05:04 +00003918void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3919 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3920 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3921 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003922}
3923
Toma Tabacu81496c12015-05-20 08:54:45 +00003924void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3925 if (!AssemblerOptions.back()->isMacro())
3926 Warning(Loc, "macro instruction expanded into multiple instructions");
3927}
3928
Daniel Sandersef638fe2014-10-03 15:37:37 +00003929void
3930MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3931 SMRange Range, bool ShowColors) {
3932 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003933 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003934 ShowColors);
3935}
3936
Jack Carter1ac53222013-02-20 23:11:17 +00003937int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003938 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003939
Vladimir Medic4c299852013-11-06 11:27:05 +00003940 CC = StringSwitch<unsigned>(Name)
3941 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003942 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003943 .Case("a0", 4)
3944 .Case("a1", 5)
3945 .Case("a2", 6)
3946 .Case("a3", 7)
3947 .Case("v0", 2)
3948 .Case("v1", 3)
3949 .Case("s0", 16)
3950 .Case("s1", 17)
3951 .Case("s2", 18)
3952 .Case("s3", 19)
3953 .Case("s4", 20)
3954 .Case("s5", 21)
3955 .Case("s6", 22)
3956 .Case("s7", 23)
3957 .Case("k0", 26)
3958 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003959 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003960 .Case("sp", 29)
3961 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003962 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003963 .Case("ra", 31)
3964 .Case("t0", 8)
3965 .Case("t1", 9)
3966 .Case("t2", 10)
3967 .Case("t3", 11)
3968 .Case("t4", 12)
3969 .Case("t5", 13)
3970 .Case("t6", 14)
3971 .Case("t7", 15)
3972 .Case("t8", 24)
3973 .Case("t9", 25)
3974 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003975
Toma Tabacufda445c2014-09-15 15:33:01 +00003976 if (!(isABI_N32() || isABI_N64()))
3977 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003978
Daniel Sandersef638fe2014-10-03 15:37:37 +00003979 if (12 <= CC && CC <= 15) {
3980 // Name is one of t4-t7
3981 AsmToken RegTok = getLexer().peekTok();
3982 SMRange RegRange = RegTok.getLocRange();
3983
3984 StringRef FixedName = StringSwitch<StringRef>(Name)
3985 .Case("t4", "t0")
3986 .Case("t5", "t1")
3987 .Case("t6", "t2")
3988 .Case("t7", "t3")
3989 .Default("");
3990 assert(FixedName != "" && "Register name is not one of t4-t7.");
3991
3992 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3993 "Did you mean $" + FixedName + "?", RegRange);
3994 }
3995
Toma Tabacufda445c2014-09-15 15:33:01 +00003996 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3997 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3998 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3999 if (8 <= CC && CC <= 11)
4000 CC += 4;
4001
4002 if (CC == -1)
4003 CC = StringSwitch<unsigned>(Name)
4004 .Case("a4", 8)
4005 .Case("a5", 9)
4006 .Case("a6", 10)
4007 .Case("a7", 11)
4008 .Case("kt0", 26)
4009 .Case("kt1", 27)
4010 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004011
4012 return CC;
4013}
Jack Carterd0bd6422013-04-18 00:41:53 +00004014
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004015int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
4016 int CC;
4017
4018 CC = StringSwitch<unsigned>(Name)
4019 .Case("hwr_cpunum", 0)
4020 .Case("hwr_synci_step", 1)
4021 .Case("hwr_cc", 2)
4022 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00004023 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004024 .Default(-1);
4025
4026 return CC;
4027}
4028
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004029int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004030
Jack Cartera63b16a2012-09-07 00:23:42 +00004031 if (Name[0] == 'f') {
4032 StringRef NumString = Name.substr(1);
4033 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004034 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004035 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004036 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00004037 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004038 return IntVal;
4039 }
4040 return -1;
4041}
Jack Cartera63b16a2012-09-07 00:23:42 +00004042
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004043int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
4044
4045 if (Name.startswith("fcc")) {
4046 StringRef NumString = Name.substr(3);
4047 unsigned IntVal;
4048 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004049 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004050 if (IntVal > 7) // There are only 8 fcc registers.
4051 return -1;
4052 return IntVal;
4053 }
4054 return -1;
4055}
4056
4057int MipsAsmParser::matchACRegisterName(StringRef Name) {
4058
Akira Hatanaka274d24c2013-08-14 01:15:52 +00004059 if (Name.startswith("ac")) {
4060 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004061 unsigned IntVal;
4062 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004063 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004064 if (IntVal > 3) // There are only 3 acc registers.
4065 return -1;
4066 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00004067 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004068 return -1;
4069}
Jack Carterd0bd6422013-04-18 00:41:53 +00004070
Jack Carter5dc8ac92013-09-25 23:50:44 +00004071int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
4072 unsigned IntVal;
4073
4074 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
4075 return -1;
4076
4077 if (IntVal > 31)
4078 return -1;
4079
4080 return IntVal;
4081}
4082
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004083int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
4084 int CC;
4085
4086 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00004087 .Case("msair", 0)
4088 .Case("msacsr", 1)
4089 .Case("msaaccess", 2)
4090 .Case("msasave", 3)
4091 .Case("msamodify", 4)
4092 .Case("msarequest", 5)
4093 .Case("msamap", 6)
4094 .Case("msaunmap", 7)
4095 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004096
4097 return CC;
4098}
4099
Toma Tabacu89a712b2015-04-15 10:48:56 +00004100unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004101 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004102 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004103 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004104 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004105 return 0;
4106 }
4107 unsigned AT = getReg(
4108 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004109 return AT;
4110}
Jack Carter0b744b32012-10-04 02:29:46 +00004111
Jack Carterd0bd6422013-04-18 00:41:53 +00004112unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004113 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004114}
4115
Toma Tabacu13964452014-09-04 13:23:44 +00004116bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004117 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004118 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004119
Jack Carter30a59822012-10-04 04:03:53 +00004120 // Check if the current operand has a custom associated parser, if so, try to
4121 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004122 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4123 if (ResTy == MatchOperand_Success)
4124 return false;
4125 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4126 // there was a match, but an error occurred, in which case, just return that
4127 // the operand parsing failed.
4128 if (ResTy == MatchOperand_ParseFail)
4129 return true;
4130
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004131 DEBUG(dbgs() << ".. Generic Parser\n");
4132
Jack Carterb4dbc172012-09-05 23:34:03 +00004133 switch (getLexer().getKind()) {
4134 default:
4135 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4136 return true;
4137 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004138 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004139 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004140
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004141 // Almost all registers have been parsed by custom parsers. There is only
4142 // one exception to this. $zero (and it's alias $0) will reach this point
4143 // for div, divu, and similar instructions because it is not an operand
4144 // to the instruction definition but an explicit register. Special case
4145 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004146 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004147 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004148
Jack Carterd0bd6422013-04-18 00:41:53 +00004149 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004150 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004151 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004152 return true;
4153
Jack Carter873c7242013-01-12 01:03:14 +00004154 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004155 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004156 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004157 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004158 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004159
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004160 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004161 return false;
4162 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004163 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004164 case AsmToken::LParen:
4165 case AsmToken::Minus:
4166 case AsmToken::Plus:
4167 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004168 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004169 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004170 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004171 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004172 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004173 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004174 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004175 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004176 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004177 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004178 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004179 return true;
4180
Jack Carter873c7242013-01-12 01:03:14 +00004181 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4182
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004183 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004184 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004185 } // case AsmToken::Percent
4186 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004187 return true;
4188}
4189
Vladimir Medic4c299852013-11-06 11:27:05 +00004190const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004191 StringRef RelocStr) {
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004192 if (RelocStr == "hi(%neg(%gp_rel")
4193 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext());
4194 else if (RelocStr == "lo(%neg(%gp_rel")
4195 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004196
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004197 MipsMCExpr::MipsExprKind Kind =
4198 StringSwitch<MipsMCExpr::MipsExprKind>(RelocStr)
4199 .Case("call16", MipsMCExpr::MEK_GOT_CALL)
4200 .Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
4201 .Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
4202 .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
4203 .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
4204 .Case("got", MipsMCExpr::MEK_GOT)
4205 .Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
4206 .Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
4207 .Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
4208 .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
4209 .Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
4210 .Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
4211 .Case("gp_rel", MipsMCExpr::MEK_GPREL)
4212 .Case("hi", MipsMCExpr::MEK_HI)
4213 .Case("higher", MipsMCExpr::MEK_HIGHER)
4214 .Case("highest", MipsMCExpr::MEK_HIGHEST)
4215 .Case("lo", MipsMCExpr::MEK_LO)
4216 .Case("neg", MipsMCExpr::MEK_NEG)
4217 .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
4218 .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
4219 .Case("tlsgd", MipsMCExpr::MEK_TLSGD)
4220 .Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
4221 .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
4222 .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
4223 .Default(MipsMCExpr::MEK_None);
Jack Carterb5cf5902013-04-17 00:18:04 +00004224
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004225 assert(Kind != MipsMCExpr::MEK_None);
4226 return MipsMCExpr::create(Kind, Expr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004227}
4228
4229bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4230
4231 switch (Expr->getKind()) {
4232 case MCExpr::Constant:
4233 return true;
4234 case MCExpr::SymbolRef:
4235 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4236 case MCExpr::Binary:
4237 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4238 if (!isEvaluated(BE->getLHS()))
4239 return false;
4240 return isEvaluated(BE->getRHS());
4241 }
4242 case MCExpr::Unary:
4243 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004244 case MCExpr::Target:
4245 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004246 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004247 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004248}
Jack Carterd0bd6422013-04-18 00:41:53 +00004249
Jack Carterb5cf5902013-04-17 00:18:04 +00004250bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004251 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004252 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004253 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004254 if (Tok.isNot(AsmToken::Identifier))
4255 return true;
4256
Yaron Keren075759a2015-03-30 15:42:36 +00004257 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004258
Jack Carterd0bd6422013-04-18 00:41:53 +00004259 Parser.Lex(); // Eat the identifier.
4260 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004261 const MCExpr *IdVal;
4262 SMLoc EndLoc;
4263
4264 if (getLexer().getKind() == AsmToken::LParen) {
4265 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004266 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004267 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004268 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004269 const AsmToken &nextTok = Parser.getTok();
4270 if (nextTok.isNot(AsmToken::Identifier))
4271 return true;
4272 Str += "(%";
4273 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004274 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004275 if (getLexer().getKind() != AsmToken::LParen)
4276 return true;
4277 } else
4278 break;
4279 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004280 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004281 return true;
4282
4283 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004284 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004285
4286 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004287 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004288
Jack Carterd0bd6422013-04-18 00:41:53 +00004289 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004290 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004291}
4292
Jack Carterb4dbc172012-09-05 23:34:03 +00004293bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4294 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004295 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004296 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004297 if (ResTy == MatchOperand_Success) {
4298 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004299 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004300 StartLoc = Operand.getStartLoc();
4301 EndLoc = Operand.getEndLoc();
4302
4303 // AFAIK, we only support numeric registers and named GPR's in CFI
4304 // directives.
4305 // Don't worry about eating tokens before failing. Using an unrecognised
4306 // register is a parse error.
4307 if (Operand.isGPRAsmReg()) {
4308 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004309 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004310 }
4311
4312 return (RegNo == (unsigned)-1);
4313 }
4314
4315 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004316 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004317}
4318
Jack Carterb5cf5902013-04-17 00:18:04 +00004319bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004320 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004321 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004322 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004323 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004324
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004325 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004326 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004327 ++NumOfLParen;
4328 }
Jack Carter873c7242013-01-12 01:03:14 +00004329
Jack Carterd0bd6422013-04-18 00:41:53 +00004330 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004331 default:
4332 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004333 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004334 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004335 case AsmToken::Integer:
4336 case AsmToken::Minus:
4337 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004338 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004339 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004340 else
4341 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004342 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004343 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004344 break;
Jack Carter873c7242013-01-12 01:03:14 +00004345 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004346 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004347 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004348 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004349}
4350
David Blaikie960ea3f2014-06-08 16:18:35 +00004351MipsAsmParser::OperandMatchResultTy
4352MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004353 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004354 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004355 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004356 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004357 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004358 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004359 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004360 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004361
Jack Carterb5cf5902013-04-17 00:18:04 +00004362 if (getLexer().getKind() == AsmToken::LParen) {
4363 Parser.Lex();
4364 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004365 }
4366
Jack Carterb5cf5902013-04-17 00:18:04 +00004367 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004368 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004369 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004370
Jack Carterd0bd6422013-04-18 00:41:53 +00004371 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004372 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004373 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004374 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004375 SMLoc E =
4376 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004377 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004378 return MatchOperand_Success;
4379 }
4380 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004381 SMLoc E =
4382 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004383
Jack Carterd0bd6422013-04-18 00:41:53 +00004384 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004385 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004386 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004387 S, E, *this);
4388 Operands.push_back(
4389 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004390 return MatchOperand_Success;
4391 }
4392 Error(Parser.getTok().getLoc(), "'(' expected");
4393 return MatchOperand_ParseFail;
4394 }
4395
Jack Carterd0bd6422013-04-18 00:41:53 +00004396 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004397 }
4398
Toma Tabacu13964452014-09-04 13:23:44 +00004399 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004400 if (Res != MatchOperand_Success)
4401 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004402
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004403 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004404 Error(Parser.getTok().getLoc(), "')' expected");
4405 return MatchOperand_ParseFail;
4406 }
4407
Jack Carter873c7242013-01-12 01:03:14 +00004408 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4409
Jack Carterd0bd6422013-04-18 00:41:53 +00004410 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004411
Craig Topper062a2ba2014-04-25 05:30:21 +00004412 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004413 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004414
Jack Carterd0bd6422013-04-18 00:41:53 +00004415 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004416 std::unique_ptr<MipsOperand> op(
4417 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004418 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004419 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004420 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004421 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004422 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4423 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004424 if (IdVal->evaluateAsAbsolute(Imm))
4425 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004426 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004427 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004428 getContext());
4429 }
4430
David Blaikie960ea3f2014-06-08 16:18:35 +00004431 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004432 return MatchOperand_Success;
4433}
4434
David Blaikie960ea3f2014-06-08 16:18:35 +00004435bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004436 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004437 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004438 if (Sym) {
4439 SMLoc S = Parser.getTok().getLoc();
4440 const MCExpr *Expr;
4441 if (Sym->isVariable())
4442 Expr = Sym->getVariableValue();
4443 else
4444 return false;
4445 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004446 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004447 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004448 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004449 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004450 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004451 if (ResTy == MatchOperand_Success) {
4452 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004453 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004454 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004455 llvm_unreachable("Should never ParseFail");
4456 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004457 }
Jack Carterd76b2372013-03-21 21:44:16 +00004458 }
4459 }
4460 return false;
4461}
Jack Carterd0bd6422013-04-18 00:41:53 +00004462
Jack Carter873c7242013-01-12 01:03:14 +00004463MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004464MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004465 StringRef Identifier,
4466 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004467 int Index = matchCPURegisterName(Identifier);
4468 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004469 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004470 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4471 return MatchOperand_Success;
4472 }
4473
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004474 Index = matchHWRegsRegisterName(Identifier);
4475 if (Index != -1) {
4476 Operands.push_back(MipsOperand::createHWRegsReg(
4477 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4478 return MatchOperand_Success;
4479 }
4480
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004481 Index = matchFPURegisterName(Identifier);
4482 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004483 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004484 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4485 return MatchOperand_Success;
4486 }
4487
4488 Index = matchFCCRegisterName(Identifier);
4489 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004490 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004491 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4492 return MatchOperand_Success;
4493 }
4494
4495 Index = matchACRegisterName(Identifier);
4496 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004497 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004498 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4499 return MatchOperand_Success;
4500 }
4501
4502 Index = matchMSA128RegisterName(Identifier);
4503 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004504 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004505 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4506 return MatchOperand_Success;
4507 }
4508
4509 Index = matchMSA128CtrlRegisterName(Identifier);
4510 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004511 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004512 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4513 return MatchOperand_Success;
4514 }
4515
4516 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004517}
4518
4519MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004520MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004521 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004522 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004523
4524 if (Token.is(AsmToken::Identifier)) {
4525 DEBUG(dbgs() << ".. identifier\n");
4526 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004527 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004528 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004529 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004530 } else if (Token.is(AsmToken::Integer)) {
4531 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004532 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004533 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4534 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004535 return MatchOperand_Success;
4536 }
4537
4538 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4539
4540 return MatchOperand_NoMatch;
4541}
4542
David Blaikie960ea3f2014-06-08 16:18:35 +00004543MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004544MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004545 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004546 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004547
4548 auto Token = Parser.getTok();
4549
4550 SMLoc S = Token.getLoc();
4551
4552 if (Token.isNot(AsmToken::Dollar)) {
4553 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4554 if (Token.is(AsmToken::Identifier)) {
4555 if (searchSymbolAlias(Operands))
4556 return MatchOperand_Success;
4557 }
4558 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4559 return MatchOperand_NoMatch;
4560 }
4561 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004562
Toma Tabacu13964452014-09-04 13:23:44 +00004563 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004564 if (ResTy == MatchOperand_Success) {
4565 Parser.Lex(); // $
4566 Parser.Lex(); // identifier
4567 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004568 return ResTy;
4569}
4570
4571MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004572MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004573 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004574 switch (getLexer().getKind()) {
4575 default:
4576 return MatchOperand_NoMatch;
4577 case AsmToken::LParen:
4578 case AsmToken::Minus:
4579 case AsmToken::Plus:
4580 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004581 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004582 case AsmToken::String:
4583 break;
4584 }
4585
4586 const MCExpr *IdVal;
4587 SMLoc S = Parser.getTok().getLoc();
4588 if (getParser().parseExpression(IdVal))
4589 return MatchOperand_ParseFail;
4590
4591 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4592 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4593 return MatchOperand_Success;
4594}
4595
David Blaikie960ea3f2014-06-08 16:18:35 +00004596MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004597MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004598 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004599 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004600
4601 SMLoc S = getLexer().getLoc();
4602
4603 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004604 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004605 if (ResTy != MatchOperand_NoMatch)
4606 return ResTy;
4607
Daniel Sanders315386c2014-04-01 10:40:14 +00004608 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004609 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004610 if (ResTy != MatchOperand_NoMatch)
4611 return ResTy;
4612
Daniel Sandersffd84362014-04-01 10:41:48 +00004613 const MCExpr *Expr = nullptr;
4614 if (Parser.parseExpression(Expr)) {
4615 // We have no way of knowing if a symbol was consumed so we must ParseFail
4616 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004617 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004618 Operands.push_back(
4619 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004620 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004621}
4622
Vladimir Medic2b953d02013-10-01 09:48:56 +00004623MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004624MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004625 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004626 const MCExpr *IdVal;
4627 // If the first token is '$' we may have register operand.
4628 if (Parser.getTok().is(AsmToken::Dollar))
4629 return MatchOperand_NoMatch;
4630 SMLoc S = Parser.getTok().getLoc();
4631 if (getParser().parseExpression(IdVal))
4632 return MatchOperand_ParseFail;
4633 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004634 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004635 int64_t Val = MCE->getValue();
4636 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4637 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004638 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004639 return MatchOperand_Success;
4640}
4641
Matheus Almeida779c5932013-11-18 12:32:49 +00004642MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004643MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4644 MCAsmParser &Parser = getParser();
4645 SmallVector<unsigned, 10> Regs;
4646 unsigned RegNo;
4647 unsigned PrevReg = Mips::NoRegister;
4648 bool RegRange = false;
4649 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4650
4651 if (Parser.getTok().isNot(AsmToken::Dollar))
4652 return MatchOperand_ParseFail;
4653
4654 SMLoc S = Parser.getTok().getLoc();
4655 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4656 SMLoc E = getLexer().getLoc();
4657 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4658 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4659 if (RegRange) {
4660 // Remove last register operand because registers from register range
4661 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004662 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4663 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004664 Regs.push_back(RegNo);
4665 } else {
4666 unsigned TmpReg = PrevReg + 1;
4667 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004668 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4669 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4670 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004671 Error(E, "invalid register operand");
4672 return MatchOperand_ParseFail;
4673 }
4674
4675 PrevReg = TmpReg;
4676 Regs.push_back(TmpReg++);
4677 }
4678 }
4679
4680 RegRange = false;
4681 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004682 if ((PrevReg == Mips::NoRegister) &&
4683 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4684 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004685 Error(E, "$16 or $31 expected");
4686 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004687 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4688 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4689 !isGP64bit()) ||
4690 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4691 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4692 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004693 Error(E, "invalid register operand");
4694 return MatchOperand_ParseFail;
4695 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004696 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4697 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4698 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004699 Error(E, "consecutive register numbers expected");
4700 return MatchOperand_ParseFail;
4701 }
4702
4703 Regs.push_back(RegNo);
4704 }
4705
4706 if (Parser.getTok().is(AsmToken::Minus))
4707 RegRange = true;
4708
4709 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4710 !Parser.getTok().isNot(AsmToken::Comma)) {
4711 Error(E, "',' or '-' expected");
4712 return MatchOperand_ParseFail;
4713 }
4714
4715 Lex(); // Consume comma or minus
4716 if (Parser.getTok().isNot(AsmToken::Dollar))
4717 break;
4718
4719 PrevReg = RegNo;
4720 }
4721
4722 SMLoc E = Parser.getTok().getLoc();
4723 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4724 parseMemOperand(Operands);
4725 return MatchOperand_Success;
4726}
4727
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004728MipsAsmParser::OperandMatchResultTy
4729MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4730 MCAsmParser &Parser = getParser();
4731
4732 SMLoc S = Parser.getTok().getLoc();
4733 if (parseAnyRegister(Operands) != MatchOperand_Success)
4734 return MatchOperand_ParseFail;
4735
4736 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00004737 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00004738
Benjamin Kramer2b68d152016-05-09 10:31:17 +00004739 Operands.pop_back();
4740 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004741 return MatchOperand_Success;
4742}
4743
Zoran Jovanovic41688672015-02-10 16:36:20 +00004744MipsAsmParser::OperandMatchResultTy
4745MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4746 MCAsmParser &Parser = getParser();
4747 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4748 SmallVector<unsigned, 10> Regs;
4749
4750 if (Parser.getTok().isNot(AsmToken::Dollar))
4751 return MatchOperand_ParseFail;
4752
4753 SMLoc S = Parser.getTok().getLoc();
4754
4755 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4756 return MatchOperand_ParseFail;
4757
4758 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4759 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4760 Regs.push_back(RegNo);
4761
4762 SMLoc E = Parser.getTok().getLoc();
4763 if (Parser.getTok().isNot(AsmToken::Comma)) {
4764 Error(E, "',' expected");
4765 return MatchOperand_ParseFail;
4766 }
4767
4768 // Remove comma.
4769 Parser.Lex();
4770
4771 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4772 return MatchOperand_ParseFail;
4773
4774 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4775 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4776 Regs.push_back(RegNo);
4777
4778 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4779
4780 return MatchOperand_Success;
4781}
4782
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004783/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4784/// either this.
4785/// ::= '(', register, ')'
4786/// handle it before we iterate so we don't get tripped up by the lack of
4787/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004788bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004789 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004790 if (getLexer().is(AsmToken::LParen)) {
4791 Operands.push_back(
4792 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4793 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004794 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004795 SMLoc Loc = getLexer().getLoc();
4796 Parser.eatToEndOfStatement();
4797 return Error(Loc, "unexpected token in argument list");
4798 }
4799 if (Parser.getTok().isNot(AsmToken::RParen)) {
4800 SMLoc Loc = getLexer().getLoc();
4801 Parser.eatToEndOfStatement();
4802 return Error(Loc, "unexpected token, expected ')'");
4803 }
4804 Operands.push_back(
4805 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4806 Parser.Lex();
4807 }
4808 return false;
4809}
4810
4811/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4812/// either one of these.
4813/// ::= '[', register, ']'
4814/// ::= '[', integer, ']'
4815/// handle it before we iterate so we don't get tripped up by the lack of
4816/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004817bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004818 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004819 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004820 if (getLexer().is(AsmToken::LBrac)) {
4821 Operands.push_back(
4822 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4823 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004824 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004825 SMLoc Loc = getLexer().getLoc();
4826 Parser.eatToEndOfStatement();
4827 return Error(Loc, "unexpected token in argument list");
4828 }
4829 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4830 SMLoc Loc = getLexer().getLoc();
4831 Parser.eatToEndOfStatement();
4832 return Error(Loc, "unexpected token, expected ']'");
4833 }
4834 Operands.push_back(
4835 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4836 Parser.Lex();
4837 }
4838 return false;
4839}
4840
David Blaikie960ea3f2014-06-08 16:18:35 +00004841bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4842 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004843 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004844 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004845
4846 // We have reached first instruction, module directive are now forbidden.
4847 getTargetStreamer().forbidModuleDirective();
4848
Vladimir Medic74593e62013-07-17 15:00:42 +00004849 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004850 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004851 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004852 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004853 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004854 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004855 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004856
4857 // Read the remaining operands.
4858 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4859 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004860 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004861 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004862 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004863 return Error(Loc, "unexpected token in argument list");
4864 }
Toma Tabacu13964452014-09-04 13:23:44 +00004865 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004866 return true;
4867 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004868
Jack Carterd0bd6422013-04-18 00:41:53 +00004869 while (getLexer().is(AsmToken::Comma)) {
4870 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004871 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004872 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004873 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004874 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004875 return Error(Loc, "unexpected token in argument list");
4876 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004877 // Parse bracket and parenthesis suffixes before we iterate
4878 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004879 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004880 return true;
4881 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004882 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004883 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004884 }
4885 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004886 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4887 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004888 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004889 return Error(Loc, "unexpected token in argument list");
4890 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004891 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004892 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004893}
4894
Nirav Dave996fc132016-05-05 14:15:46 +00004895// FIXME: Given that these have the same name, these should both be
4896// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004897bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004898 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004899 SMLoc Loc = getLexer().getLoc();
4900 Parser.eatToEndOfStatement();
4901 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004902}
4903
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004904bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004905 return Error(Loc, ErrorMsg);
4906}
4907
Jack Carter0b744b32012-10-04 02:29:46 +00004908bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004909 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004910 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004911
4912 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004913 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004914
4915 Parser.Lex(); // Eat "noat".
4916
Jack Carterd0bd6422013-04-18 00:41:53 +00004917 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004918 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004919 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004920 return false;
4921 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004922
4923 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004924 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004925 return false;
4926}
Jack Carterd0bd6422013-04-18 00:41:53 +00004927
Jack Carter0b744b32012-10-04 02:29:46 +00004928bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004929 // Line can be: ".set at", which sets $at to $1
4930 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004931 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004932 Parser.Lex(); // Eat "at".
4933
Jack Carter0b744b32012-10-04 02:29:46 +00004934 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004935 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004936 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004937
4938 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004939 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004940 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004941 }
4942
4943 if (getLexer().isNot(AsmToken::Equal)) {
4944 reportParseError("unexpected token, expected equals sign");
4945 return false;
4946 }
4947 Parser.Lex(); // Eat "=".
4948
4949 if (getLexer().isNot(AsmToken::Dollar)) {
4950 if (getLexer().is(AsmToken::EndOfStatement)) {
4951 reportParseError("no register specified");
4952 return false;
4953 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004954 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004955 return false;
4956 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004957 }
4958 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004959
Toma Tabacu16a74492015-02-13 10:30:57 +00004960 // Find out what "reg" is.
4961 unsigned AtRegNo;
4962 const AsmToken &Reg = Parser.getTok();
4963 if (Reg.is(AsmToken::Identifier)) {
4964 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4965 } else if (Reg.is(AsmToken::Integer)) {
4966 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004967 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004968 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004969 return false;
4970 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004971
4972 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004973 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004974 reportParseError("invalid register");
4975 return false;
4976 }
4977 Parser.Lex(); // Eat "reg".
4978
4979 // If this is not the end of the statement, report an error.
4980 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4981 reportParseError("unexpected token, expected end of statement");
4982 return false;
4983 }
4984
4985 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4986
4987 Parser.Lex(); // Consume the EndOfStatement.
4988 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004989}
4990
4991bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004992 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004993 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004994 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004995 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004996 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004997 return false;
4998 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004999 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00005000 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005001 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005002 return false;
5003}
5004
5005bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005006 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005007 Parser.Lex();
5008 // If this is not the end of the statement, report an error.
5009 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005010 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005011 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005012 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005013 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005014 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005015 Parser.Lex(); // Consume the EndOfStatement.
5016 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005017}
5018
5019bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005020 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005021 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005022 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005023 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005024 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005025 return false;
5026 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005027 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005028 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005029 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005030 return false;
5031}
5032
5033bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005034 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005035 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005036 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005037 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005038 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005039 return false;
5040 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005041 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005042 reportParseError("`noreorder' must be set before `nomacro'");
5043 return false;
5044 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005045 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005046 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005047 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005048 return false;
5049}
Jack Carterd76b2372013-03-21 21:44:16 +00005050
Daniel Sanders44934432014-08-07 12:03:36 +00005051bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005052 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005053 Parser.Lex();
5054
5055 // If this is not the end of the statement, report an error.
5056 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005057 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005058
5059 setFeatureBits(Mips::FeatureMSA, "msa");
5060 getTargetStreamer().emitDirectiveSetMsa();
5061 return false;
5062}
5063
5064bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005065 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005066 Parser.Lex();
5067
5068 // If this is not the end of the statement, report an error.
5069 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005070 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005071
5072 clearFeatureBits(Mips::FeatureMSA, "msa");
5073 getTargetStreamer().emitDirectiveSetNoMsa();
5074 return false;
5075}
5076
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005077bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005078 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005079 Parser.Lex(); // Eat "nodsp".
5080
5081 // If this is not the end of the statement, report an error.
5082 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5083 reportParseError("unexpected token, expected end of statement");
5084 return false;
5085 }
5086
5087 clearFeatureBits(Mips::FeatureDSP, "dsp");
5088 getTargetStreamer().emitDirectiveSetNoDsp();
5089 return false;
5090}
5091
Toma Tabacucc2502d2014-11-04 17:18:07 +00005092bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005093 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005094 Parser.Lex(); // Eat "mips16".
5095
Jack Carter39536722014-01-22 23:08:42 +00005096 // If this is not the end of the statement, report an error.
5097 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005098 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005099 return false;
5100 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005101
5102 setFeatureBits(Mips::FeatureMips16, "mips16");
5103 getTargetStreamer().emitDirectiveSetMips16();
5104 Parser.Lex(); // Consume the EndOfStatement.
5105 return false;
5106}
5107
5108bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005109 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005110 Parser.Lex(); // Eat "nomips16".
5111
5112 // If this is not the end of the statement, report an error.
5113 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5114 reportParseError("unexpected token, expected end of statement");
5115 return false;
5116 }
5117
5118 clearFeatureBits(Mips::FeatureMips16, "mips16");
5119 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005120 Parser.Lex(); // Consume the EndOfStatement.
5121 return false;
5122}
5123
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005124bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005125 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005126 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005127 // Line can be: .set fp=32
5128 // .set fp=xx
5129 // .set fp=64
5130 Parser.Lex(); // Eat fp token
5131 AsmToken Tok = Parser.getTok();
5132 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005133 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005134 return false;
5135 }
5136 Parser.Lex(); // Eat '=' token.
5137 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005138
5139 if (!parseFpABIValue(FpAbiVal, ".set"))
5140 return false;
5141
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005142 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005143 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005144 return false;
5145 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005146 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005147 Parser.Lex(); // Consume the EndOfStatement.
5148 return false;
5149}
5150
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005151bool MipsAsmParser::parseSetOddSPRegDirective() {
5152 MCAsmParser &Parser = getParser();
5153
5154 Parser.Lex(); // Eat "oddspreg".
5155 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5156 reportParseError("unexpected token, expected end of statement");
5157 return false;
5158 }
5159
5160 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5161 getTargetStreamer().emitDirectiveSetOddSPReg();
5162 return false;
5163}
5164
5165bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5166 MCAsmParser &Parser = getParser();
5167
5168 Parser.Lex(); // Eat "nooddspreg".
5169 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5170 reportParseError("unexpected token, expected end of statement");
5171 return false;
5172 }
5173
5174 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5175 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5176 return false;
5177}
5178
Toma Tabacu9db22db2014-09-09 10:15:38 +00005179bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005180 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005181 SMLoc Loc = getLexer().getLoc();
5182
5183 Parser.Lex();
5184 if (getLexer().isNot(AsmToken::EndOfStatement))
5185 return reportParseError("unexpected token, expected end of statement");
5186
5187 // Always keep an element on the options "stack" to prevent the user
5188 // from changing the initial options. This is how we remember them.
5189 if (AssemblerOptions.size() == 2)
5190 return reportParseError(Loc, ".set pop with no .set push");
5191
Akira Hatanakab11ef082015-11-14 06:35:56 +00005192 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005193 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005194 setAvailableFeatures(
5195 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5196 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005197
5198 getTargetStreamer().emitDirectiveSetPop();
5199 return false;
5200}
5201
5202bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005203 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005204 Parser.Lex();
5205 if (getLexer().isNot(AsmToken::EndOfStatement))
5206 return reportParseError("unexpected token, expected end of statement");
5207
5208 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005209 AssemblerOptions.push_back(
5210 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005211
5212 getTargetStreamer().emitDirectiveSetPush();
5213 return false;
5214}
5215
Toma Tabacu29696502015-06-02 09:48:04 +00005216bool MipsAsmParser::parseSetSoftFloatDirective() {
5217 MCAsmParser &Parser = getParser();
5218 Parser.Lex();
5219 if (getLexer().isNot(AsmToken::EndOfStatement))
5220 return reportParseError("unexpected token, expected end of statement");
5221
5222 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5223 getTargetStreamer().emitDirectiveSetSoftFloat();
5224 return false;
5225}
5226
5227bool MipsAsmParser::parseSetHardFloatDirective() {
5228 MCAsmParser &Parser = getParser();
5229 Parser.Lex();
5230 if (getLexer().isNot(AsmToken::EndOfStatement))
5231 return reportParseError("unexpected token, expected end of statement");
5232
5233 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5234 getTargetStreamer().emitDirectiveSetHardFloat();
5235 return false;
5236}
5237
Jack Carterd76b2372013-03-21 21:44:16 +00005238bool MipsAsmParser::parseSetAssignment() {
5239 StringRef Name;
5240 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005241 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005242
5243 if (Parser.parseIdentifier(Name))
5244 reportParseError("expected identifier after .set");
5245
5246 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005247 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005248 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005249
Jack Carter3b2c96e2014-01-22 23:31:38 +00005250 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005251 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005252
Jim Grosbach6f482002015-05-18 18:43:14 +00005253 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005254 Sym->setVariableValue(Value);
5255
5256 return false;
5257}
Jack Carterd0bd6422013-04-18 00:41:53 +00005258
Toma Tabacu26647792014-09-09 12:52:14 +00005259bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005260 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005261 Parser.Lex();
5262 if (getLexer().isNot(AsmToken::EndOfStatement))
5263 return reportParseError("unexpected token, expected end of statement");
5264
5265 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005266 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005267 setAvailableFeatures(
5268 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5269 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005270 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5271
5272 getTargetStreamer().emitDirectiveSetMips0();
5273 return false;
5274}
5275
Toma Tabacu85618b32014-08-19 14:22:52 +00005276bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005277 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005278 Parser.Lex();
5279 if (getLexer().isNot(AsmToken::Equal))
5280 return reportParseError("unexpected token, expected equals sign");
5281
5282 Parser.Lex();
5283 StringRef Arch;
5284 if (Parser.parseIdentifier(Arch))
5285 return reportParseError("expected arch identifier");
5286
5287 StringRef ArchFeatureName =
5288 StringSwitch<StringRef>(Arch)
5289 .Case("mips1", "mips1")
5290 .Case("mips2", "mips2")
5291 .Case("mips3", "mips3")
5292 .Case("mips4", "mips4")
5293 .Case("mips5", "mips5")
5294 .Case("mips32", "mips32")
5295 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005296 .Case("mips32r3", "mips32r3")
5297 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005298 .Case("mips32r6", "mips32r6")
5299 .Case("mips64", "mips64")
5300 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005301 .Case("mips64r3", "mips64r3")
5302 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005303 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005304 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005305 .Case("r4000", "mips3") // This is an implementation of Mips3.
5306 .Default("");
5307
5308 if (ArchFeatureName.empty())
5309 return reportParseError("unsupported architecture");
5310
5311 selectArch(ArchFeatureName);
5312 getTargetStreamer().emitDirectiveSetArch(Arch);
5313 return false;
5314}
5315
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005316bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005317 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005318 Parser.Lex();
5319 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005320 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005321
Matheus Almeida2852af82014-04-22 10:15:54 +00005322 switch (Feature) {
5323 default:
5324 llvm_unreachable("Unimplemented feature");
5325 case Mips::FeatureDSP:
5326 setFeatureBits(Mips::FeatureDSP, "dsp");
5327 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005328 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005329 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00005330 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00005331 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005332 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005333 case Mips::FeatureMips1:
5334 selectArch("mips1");
5335 getTargetStreamer().emitDirectiveSetMips1();
5336 break;
5337 case Mips::FeatureMips2:
5338 selectArch("mips2");
5339 getTargetStreamer().emitDirectiveSetMips2();
5340 break;
5341 case Mips::FeatureMips3:
5342 selectArch("mips3");
5343 getTargetStreamer().emitDirectiveSetMips3();
5344 break;
5345 case Mips::FeatureMips4:
5346 selectArch("mips4");
5347 getTargetStreamer().emitDirectiveSetMips4();
5348 break;
5349 case Mips::FeatureMips5:
5350 selectArch("mips5");
5351 getTargetStreamer().emitDirectiveSetMips5();
5352 break;
5353 case Mips::FeatureMips32:
5354 selectArch("mips32");
5355 getTargetStreamer().emitDirectiveSetMips32();
5356 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005357 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005358 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005359 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005360 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005361 case Mips::FeatureMips32r3:
5362 selectArch("mips32r3");
5363 getTargetStreamer().emitDirectiveSetMips32R3();
5364 break;
5365 case Mips::FeatureMips32r5:
5366 selectArch("mips32r5");
5367 getTargetStreamer().emitDirectiveSetMips32R5();
5368 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005369 case Mips::FeatureMips32r6:
5370 selectArch("mips32r6");
5371 getTargetStreamer().emitDirectiveSetMips32R6();
5372 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005373 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005374 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005375 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005376 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005377 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005378 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005379 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005380 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005381 case Mips::FeatureMips64r3:
5382 selectArch("mips64r3");
5383 getTargetStreamer().emitDirectiveSetMips64R3();
5384 break;
5385 case Mips::FeatureMips64r5:
5386 selectArch("mips64r5");
5387 getTargetStreamer().emitDirectiveSetMips64R5();
5388 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005389 case Mips::FeatureMips64r6:
5390 selectArch("mips64r6");
5391 getTargetStreamer().emitDirectiveSetMips64R6();
5392 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005393 }
5394 return false;
5395}
5396
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005397bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005398 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005399 if (getLexer().isNot(AsmToken::Comma)) {
5400 SMLoc Loc = getLexer().getLoc();
5401 Parser.eatToEndOfStatement();
5402 return Error(Loc, ErrorStr);
5403 }
5404
Matheus Almeida2852af82014-04-22 10:15:54 +00005405 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005406 return true;
5407}
5408
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005409// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5410// In this class, it is only used for .cprestore.
5411// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5412// MipsTargetELFStreamer and MipsAsmParser.
5413bool MipsAsmParser::isPicAndNotNxxAbi() {
5414 return inPicMode() && !(isABI_N32() || isABI_N64());
5415}
5416
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005417bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005418 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005419 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005420
Toma Tabacudde4c462014-11-06 10:02:45 +00005421 if (inMips16Mode()) {
5422 reportParseError(".cpload is not supported in Mips16 mode");
5423 return false;
5424 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005425
David Blaikie960ea3f2014-06-08 16:18:35 +00005426 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005427 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005428 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5429 reportParseError("expected register containing function address");
5430 return false;
5431 }
5432
David Blaikie960ea3f2014-06-08 16:18:35 +00005433 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5434 if (!RegOpnd.isGPRAsmReg()) {
5435 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005436 return false;
5437 }
5438
Toma Tabacudde4c462014-11-06 10:02:45 +00005439 // If this is not the end of the statement, report an error.
5440 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5441 reportParseError("unexpected token, expected end of statement");
5442 return false;
5443 }
5444
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005445 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005446 return false;
5447}
5448
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005449bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5450 MCAsmParser &Parser = getParser();
5451
5452 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5453 // is used in non-PIC mode.
5454
5455 if (inMips16Mode()) {
5456 reportParseError(".cprestore is not supported in Mips16 mode");
5457 return false;
5458 }
5459
5460 // Get the stack offset value.
5461 const MCExpr *StackOffset;
5462 int64_t StackOffsetVal;
5463 if (Parser.parseExpression(StackOffset)) {
5464 reportParseError("expected stack offset value");
5465 return false;
5466 }
5467
5468 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5469 reportParseError("stack offset is not an absolute expression");
5470 return false;
5471 }
5472
5473 if (StackOffsetVal < 0) {
5474 Warning(Loc, ".cprestore with negative stack offset has no effect");
5475 IsCpRestoreSet = false;
5476 } else {
5477 IsCpRestoreSet = true;
5478 CpRestoreOffset = StackOffsetVal;
5479 }
5480
5481 // If this is not the end of the statement, report an error.
5482 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5483 reportParseError("unexpected token, expected end of statement");
5484 return false;
5485 }
5486
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005487 if (!getTargetStreamer().emitDirectiveCpRestore(
5488 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005489 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005490 Parser.Lex(); // Consume the EndOfStatement.
5491 return false;
5492}
5493
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005494bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005495 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005496 unsigned FuncReg;
5497 unsigned Save;
5498 bool SaveIsReg = true;
5499
Matheus Almeida7e815762014-06-18 13:08:59 +00005500 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005501 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005502 if (ResTy == MatchOperand_NoMatch) {
5503 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005504 return false;
5505 }
5506
5507 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5508 if (!FuncRegOpnd.isGPRAsmReg()) {
5509 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5510 Parser.eatToEndOfStatement();
5511 return false;
5512 }
5513
5514 FuncReg = FuncRegOpnd.getGPR32Reg();
5515 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005516
Toma Tabacu65f10572014-09-16 15:00:52 +00005517 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005518 return true;
5519
Toma Tabacu13964452014-09-04 13:23:44 +00005520 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005521 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005522 const MCExpr *OffsetExpr;
5523 int64_t OffsetVal;
5524 SMLoc ExprLoc = getLexer().getLoc();
5525
5526 if (Parser.parseExpression(OffsetExpr) ||
5527 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5528 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005529 Parser.eatToEndOfStatement();
5530 return false;
5531 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005532
5533 Save = OffsetVal;
5534 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005535 } else {
5536 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5537 if (!SaveOpnd.isGPRAsmReg()) {
5538 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5539 Parser.eatToEndOfStatement();
5540 return false;
5541 }
5542 Save = SaveOpnd.getGPR32Reg();
5543 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005544
Toma Tabacu65f10572014-09-16 15:00:52 +00005545 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005546 return true;
5547
Toma Tabacu8874eac2015-02-18 13:46:53 +00005548 const MCExpr *Expr;
5549 if (Parser.parseExpression(Expr)) {
5550 reportParseError("expected expression");
5551 return false;
5552 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005553
Toma Tabacu8874eac2015-02-18 13:46:53 +00005554 if (Expr->getKind() != MCExpr::SymbolRef) {
5555 reportParseError("expected symbol");
5556 return false;
5557 }
5558 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5559
Daniel Sandersf173dda2015-09-22 10:50:09 +00005560 CpSaveLocation = Save;
5561 CpSaveLocationIsRegister = SaveIsReg;
5562
Toma Tabacu8874eac2015-02-18 13:46:53 +00005563 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5564 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005565 return false;
5566}
5567
Daniel Sandersf173dda2015-09-22 10:50:09 +00005568bool MipsAsmParser::parseDirectiveCPReturn() {
5569 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5570 CpSaveLocationIsRegister);
5571 return false;
5572}
5573
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005574bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005575 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005576 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5577 const AsmToken &Tok = Parser.getTok();
5578
5579 if (Tok.getString() == "2008") {
5580 Parser.Lex();
5581 getTargetStreamer().emitDirectiveNaN2008();
5582 return false;
5583 } else if (Tok.getString() == "legacy") {
5584 Parser.Lex();
5585 getTargetStreamer().emitDirectiveNaNLegacy();
5586 return false;
5587 }
5588 }
5589 // If we don't recognize the option passed to the .nan
5590 // directive (e.g. no option or unknown option), emit an error.
5591 reportParseError("invalid option in .nan directive");
5592 return false;
5593}
5594
Jack Carter0b744b32012-10-04 02:29:46 +00005595bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005596 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005597 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005598 const AsmToken &Tok = Parser.getTok();
5599
5600 if (Tok.getString() == "noat") {
5601 return parseSetNoAtDirective();
5602 } else if (Tok.getString() == "at") {
5603 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005604 } else if (Tok.getString() == "arch") {
5605 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005606 } else if (Tok.getString() == "fp") {
5607 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005608 } else if (Tok.getString() == "oddspreg") {
5609 return parseSetOddSPRegDirective();
5610 } else if (Tok.getString() == "nooddspreg") {
5611 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005612 } else if (Tok.getString() == "pop") {
5613 return parseSetPopDirective();
5614 } else if (Tok.getString() == "push") {
5615 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005616 } else if (Tok.getString() == "reorder") {
5617 return parseSetReorderDirective();
5618 } else if (Tok.getString() == "noreorder") {
5619 return parseSetNoReorderDirective();
5620 } else if (Tok.getString() == "macro") {
5621 return parseSetMacroDirective();
5622 } else if (Tok.getString() == "nomacro") {
5623 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005624 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005625 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005626 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005627 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005628 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00005629 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005630 getTargetStreamer().emitDirectiveSetNoMicroMips();
5631 Parser.eatToEndOfStatement();
5632 return false;
5633 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005634 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005635 } else if (Tok.getString() == "mips0") {
5636 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005637 } else if (Tok.getString() == "mips1") {
5638 return parseSetFeature(Mips::FeatureMips1);
5639 } else if (Tok.getString() == "mips2") {
5640 return parseSetFeature(Mips::FeatureMips2);
5641 } else if (Tok.getString() == "mips3") {
5642 return parseSetFeature(Mips::FeatureMips3);
5643 } else if (Tok.getString() == "mips4") {
5644 return parseSetFeature(Mips::FeatureMips4);
5645 } else if (Tok.getString() == "mips5") {
5646 return parseSetFeature(Mips::FeatureMips5);
5647 } else if (Tok.getString() == "mips32") {
5648 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005649 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005650 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005651 } else if (Tok.getString() == "mips32r3") {
5652 return parseSetFeature(Mips::FeatureMips32r3);
5653 } else if (Tok.getString() == "mips32r5") {
5654 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005655 } else if (Tok.getString() == "mips32r6") {
5656 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005657 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005658 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005659 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005660 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005661 } else if (Tok.getString() == "mips64r3") {
5662 return parseSetFeature(Mips::FeatureMips64r3);
5663 } else if (Tok.getString() == "mips64r5") {
5664 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005665 } else if (Tok.getString() == "mips64r6") {
5666 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005667 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005668 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005669 } else if (Tok.getString() == "nodsp") {
5670 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005671 } else if (Tok.getString() == "msa") {
5672 return parseSetMsaDirective();
5673 } else if (Tok.getString() == "nomsa") {
5674 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005675 } else if (Tok.getString() == "softfloat") {
5676 return parseSetSoftFloatDirective();
5677 } else if (Tok.getString() == "hardfloat") {
5678 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005679 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005680 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005681 parseSetAssignment();
5682 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005683 }
Jack Carter07c818d2013-01-25 01:31:34 +00005684
Jack Carter0b744b32012-10-04 02:29:46 +00005685 return true;
5686}
5687
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005688/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005689/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005690bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005691 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005692 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5693 for (;;) {
5694 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005695 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005696 return true;
5697
5698 getParser().getStreamer().EmitValue(Value, Size);
5699
5700 if (getLexer().is(AsmToken::EndOfStatement))
5701 break;
5702
Jack Carter07c818d2013-01-25 01:31:34 +00005703 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005704 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005705 Parser.Lex();
5706 }
5707 }
5708
5709 Parser.Lex();
5710 return false;
5711}
5712
Vladimir Medic4c299852013-11-06 11:27:05 +00005713/// parseDirectiveGpWord
5714/// ::= .gpword local_sym
5715bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005716 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005717 const MCExpr *Value;
5718 // EmitGPRel32Value requires an expression, so we are using base class
5719 // method to evaluate the expression.
5720 if (getParser().parseExpression(Value))
5721 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005722 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005723
Vladimir Medice10c1122013-11-13 13:18:04 +00005724 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005725 return Error(getLexer().getLoc(),
5726 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005727 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005728 return false;
5729}
5730
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005731/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005732/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005733bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005734 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005735 const MCExpr *Value;
5736 // EmitGPRel64Value requires an expression, so we are using base class
5737 // method to evaluate the expression.
5738 if (getParser().parseExpression(Value))
5739 return true;
5740 getParser().getStreamer().EmitGPRel64Value(Value);
5741
5742 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005743 return Error(getLexer().getLoc(),
5744 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005745 Parser.Lex(); // Eat EndOfStatement token.
5746 return false;
5747}
5748
Jack Carter0cd3c192014-01-06 23:27:31 +00005749bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005750 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005751 // Get the option token.
5752 AsmToken Tok = Parser.getTok();
5753 // At the moment only identifiers are supported.
5754 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005755 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005756 Parser.eatToEndOfStatement();
5757 return false;
5758 }
5759
5760 StringRef Option = Tok.getIdentifier();
5761
5762 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005763 // MipsAsmParser needs to know if the current PIC mode changes.
5764 IsPicEnabled = false;
5765
Jack Carter0cd3c192014-01-06 23:27:31 +00005766 getTargetStreamer().emitDirectiveOptionPic0();
5767 Parser.Lex();
5768 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5769 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005770 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005771 Parser.eatToEndOfStatement();
5772 }
5773 return false;
5774 }
5775
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005776 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005777 // MipsAsmParser needs to know if the current PIC mode changes.
5778 IsPicEnabled = true;
5779
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005780 getTargetStreamer().emitDirectiveOptionPic2();
5781 Parser.Lex();
5782 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5783 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005784 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005785 Parser.eatToEndOfStatement();
5786 }
5787 return false;
5788 }
5789
Jack Carter0cd3c192014-01-06 23:27:31 +00005790 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005791 Warning(Parser.getTok().getLoc(),
5792 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005793 Parser.eatToEndOfStatement();
5794 return false;
5795}
5796
Toma Tabacu9ca50962015-04-16 09:53:47 +00005797/// parseInsnDirective
5798/// ::= .insn
5799bool MipsAsmParser::parseInsnDirective() {
5800 // If this is not the end of the statement, report an error.
5801 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5802 reportParseError("unexpected token, expected end of statement");
5803 return false;
5804 }
5805
5806 // The actual label marking happens in
5807 // MipsELFStreamer::createPendingLabelRelocs().
5808 getTargetStreamer().emitDirectiveInsn();
5809
5810 getParser().Lex(); // Eat EndOfStatement token.
5811 return false;
5812}
5813
Simon Atanasyanbe186202016-02-11 06:45:54 +00005814/// parseSSectionDirective
5815/// ::= .sbss
5816/// ::= .sdata
5817bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5818 // If this is not the end of the statement, report an error.
5819 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5820 reportParseError("unexpected token, expected end of statement");
5821 return false;
5822 }
5823
5824 MCSection *ELFSection = getContext().getELFSection(
5825 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5826 getParser().getStreamer().SwitchSection(ELFSection);
5827
5828 getParser().Lex(); // Eat EndOfStatement token.
5829 return false;
5830}
5831
Daniel Sanders7e527422014-07-10 13:38:23 +00005832/// parseDirectiveModule
5833/// ::= .module oddspreg
5834/// ::= .module nooddspreg
5835/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005836/// ::= .module softfloat
5837/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005838bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005839 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005840 MCAsmLexer &Lexer = getLexer();
5841 SMLoc L = Lexer.getLoc();
5842
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005843 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005844 // TODO : get a better message.
5845 reportParseError(".module directive must appear before any code");
5846 return false;
5847 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005848
Toma Tabacuc405c822015-01-23 10:40:19 +00005849 StringRef Option;
5850 if (Parser.parseIdentifier(Option)) {
5851 reportParseError("expected .module option identifier");
5852 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005853 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005854
Toma Tabacuc405c822015-01-23 10:40:19 +00005855 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005856 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005857
Toma Tabacu3c499582015-06-25 10:56:57 +00005858 // Synchronize the abiflags information with the FeatureBits information we
5859 // changed above.
5860 getTargetStreamer().updateABIInfo(*this);
5861
5862 // If printing assembly, use the recently updated abiflags information.
5863 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5864 // emitted at the end).
5865 getTargetStreamer().emitDirectiveModuleOddSPReg();
5866
Toma Tabacuc405c822015-01-23 10:40:19 +00005867 // If this is not the end of the statement, report an error.
5868 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5869 reportParseError("unexpected token, expected end of statement");
5870 return false;
5871 }
5872
5873 return false; // parseDirectiveModule has finished successfully.
5874 } else if (Option == "nooddspreg") {
5875 if (!isABI_O32()) {
5876 Error(L, "'.module nooddspreg' requires the O32 ABI");
5877 return false;
5878 }
5879
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005880 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005881
Toma Tabacu3c499582015-06-25 10:56:57 +00005882 // Synchronize the abiflags information with the FeatureBits information we
5883 // changed above.
5884 getTargetStreamer().updateABIInfo(*this);
5885
5886 // If printing assembly, use the recently updated abiflags information.
5887 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5888 // emitted at the end).
5889 getTargetStreamer().emitDirectiveModuleOddSPReg();
5890
Toma Tabacuc405c822015-01-23 10:40:19 +00005891 // If this is not the end of the statement, report an error.
5892 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5893 reportParseError("unexpected token, expected end of statement");
5894 return false;
5895 }
5896
5897 return false; // parseDirectiveModule has finished successfully.
5898 } else if (Option == "fp") {
5899 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005900 } else if (Option == "softfloat") {
5901 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5902
5903 // Synchronize the ABI Flags information with the FeatureBits information we
5904 // updated above.
5905 getTargetStreamer().updateABIInfo(*this);
5906
5907 // If printing assembly, use the recently updated ABI Flags information.
5908 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5909 // emitted later).
5910 getTargetStreamer().emitDirectiveModuleSoftFloat();
5911
5912 // If this is not the end of the statement, report an error.
5913 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5914 reportParseError("unexpected token, expected end of statement");
5915 return false;
5916 }
5917
5918 return false; // parseDirectiveModule has finished successfully.
5919 } else if (Option == "hardfloat") {
5920 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5921
5922 // Synchronize the ABI Flags information with the FeatureBits information we
5923 // updated above.
5924 getTargetStreamer().updateABIInfo(*this);
5925
5926 // If printing assembly, use the recently updated ABI Flags information.
5927 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5928 // emitted later).
5929 getTargetStreamer().emitDirectiveModuleHardFloat();
5930
5931 // If this is not the end of the statement, report an error.
5932 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5933 reportParseError("unexpected token, expected end of statement");
5934 return false;
5935 }
5936
5937 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005938 } else {
5939 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5940 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005941}
5942
5943/// parseDirectiveModuleFP
5944/// ::= =32
5945/// ::= =xx
5946/// ::= =64
5947bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005948 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005949 MCAsmLexer &Lexer = getLexer();
5950
5951 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005952 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005953 return false;
5954 }
5955 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005956
Daniel Sanders7e527422014-07-10 13:38:23 +00005957 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005958 if (!parseFpABIValue(FpABI, ".module"))
5959 return false;
5960
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005961 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005962 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005963 return false;
5964 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005965
Toma Tabacua64e5402015-06-25 12:44:38 +00005966 // Synchronize the abiflags information with the FeatureBits information we
5967 // changed above.
5968 getTargetStreamer().updateABIInfo(*this);
5969
5970 // If printing assembly, use the recently updated abiflags information.
5971 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5972 // emitted at the end).
5973 getTargetStreamer().emitDirectiveModuleFP();
5974
Daniel Sanders7e527422014-07-10 13:38:23 +00005975 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005976 return false;
5977}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005978
Daniel Sanders7e527422014-07-10 13:38:23 +00005979bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005980 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005981 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005982 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005983 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005984
5985 if (Lexer.is(AsmToken::Identifier)) {
5986 StringRef Value = Parser.getTok().getString();
5987 Parser.Lex();
5988
5989 if (Value != "xx") {
5990 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5991 return false;
5992 }
5993
5994 if (!isABI_O32()) {
5995 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5996 return false;
5997 }
5998
Daniel Sanders7e527422014-07-10 13:38:23 +00005999 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006000 if (ModuleLevelOptions) {
6001 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6002 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6003 } else {
6004 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6005 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6006 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006007 return true;
6008 }
6009
6010 if (Lexer.is(AsmToken::Integer)) {
6011 unsigned Value = Parser.getTok().getIntVal();
6012 Parser.Lex();
6013
6014 if (Value != 32 && Value != 64) {
6015 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6016 return false;
6017 }
6018
6019 if (Value == 32) {
6020 if (!isABI_O32()) {
6021 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6022 return false;
6023 }
6024
Daniel Sanders7e527422014-07-10 13:38:23 +00006025 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006026 if (ModuleLevelOptions) {
6027 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6028 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6029 } else {
6030 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6031 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6032 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006033 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006034 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006035 if (ModuleLevelOptions) {
6036 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6037 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6038 } else {
6039 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6040 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6041 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006042 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006043
Daniel Sanders7e527422014-07-10 13:38:23 +00006044 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006045 }
6046
6047 return false;
6048}
6049
Jack Carter0b744b32012-10-04 02:29:46 +00006050bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006051 // This returns false if this function recognizes the directive
6052 // regardless of whether it is successfully handles or reports an
6053 // error. Otherwise it returns true to give the generic parser a
6054 // chance at recognizing it.
6055
Rafael Espindola961d4692014-11-11 05:18:41 +00006056 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006057 StringRef IDVal = DirectiveID.getString();
6058
Nirav Dave996fc132016-05-05 14:15:46 +00006059 if (IDVal == ".cpload") {
6060 parseDirectiveCpLoad(DirectiveID.getLoc());
6061 return false;
6062 }
6063 if (IDVal == ".cprestore") {
6064 parseDirectiveCpRestore(DirectiveID.getLoc());
6065 return false;
6066 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006067 if (IDVal == ".dword") {
6068 parseDataDirective(8, DirectiveID.getLoc());
6069 return false;
6070 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006071 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006072 StringRef SymbolName;
6073
6074 if (Parser.parseIdentifier(SymbolName)) {
6075 reportParseError("expected identifier after .ent");
6076 return false;
6077 }
6078
6079 // There's an undocumented extension that allows an integer to
6080 // follow the name of the procedure which AFAICS is ignored by GAS.
6081 // Example: .ent foo,2
6082 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6083 if (getLexer().isNot(AsmToken::Comma)) {
6084 // Even though we accept this undocumented extension for compatibility
6085 // reasons, the additional integer argument does not actually change
6086 // the behaviour of the '.ent' directive, so we would like to discourage
6087 // its use. We do this by not referring to the extended version in
6088 // error messages which are not directly related to its use.
6089 reportParseError("unexpected token, expected end of statement");
6090 return false;
6091 }
6092 Parser.Lex(); // Eat the comma.
6093 const MCExpr *DummyNumber;
6094 int64_t DummyNumberVal;
6095 // If the user was explicitly trying to use the extended version,
6096 // we still give helpful extension-related error messages.
6097 if (Parser.parseExpression(DummyNumber)) {
6098 reportParseError("expected number after comma");
6099 return false;
6100 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006101 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006102 reportParseError("expected an absolute expression after comma");
6103 return false;
6104 }
6105 }
6106
6107 // If this is not the end of the statement, report an error.
6108 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6109 reportParseError("unexpected token, expected end of statement");
6110 return false;
6111 }
6112
Jim Grosbach6f482002015-05-18 18:43:14 +00006113 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006114
6115 getTargetStreamer().emitDirectiveEnt(*Sym);
6116 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006117 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006118 return false;
6119 }
6120
Jack Carter07c818d2013-01-25 01:31:34 +00006121 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006122 StringRef SymbolName;
6123
6124 if (Parser.parseIdentifier(SymbolName)) {
6125 reportParseError("expected identifier after .end");
6126 return false;
6127 }
6128
6129 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6130 reportParseError("unexpected token, expected end of statement");
6131 return false;
6132 }
6133
6134 if (CurrentFn == nullptr) {
6135 reportParseError(".end used without .ent");
6136 return false;
6137 }
6138
6139 if ((SymbolName != CurrentFn->getName())) {
6140 reportParseError(".end symbol does not match .ent symbol");
6141 return false;
6142 }
6143
6144 getTargetStreamer().emitDirectiveEnd(SymbolName);
6145 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006146 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006147 return false;
6148 }
6149
Jack Carter07c818d2013-01-25 01:31:34 +00006150 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006151 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6152 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006153 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006154 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6155 reportParseError("expected stack register");
6156 return false;
6157 }
6158
6159 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6160 if (!StackRegOpnd.isGPRAsmReg()) {
6161 reportParseError(StackRegOpnd.getStartLoc(),
6162 "expected general purpose register");
6163 return false;
6164 }
6165 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6166
6167 if (Parser.getTok().is(AsmToken::Comma))
6168 Parser.Lex();
6169 else {
6170 reportParseError("unexpected token, expected comma");
6171 return false;
6172 }
6173
6174 // Parse the frame size.
6175 const MCExpr *FrameSize;
6176 int64_t FrameSizeVal;
6177
6178 if (Parser.parseExpression(FrameSize)) {
6179 reportParseError("expected frame size value");
6180 return false;
6181 }
6182
Jim Grosbach13760bd2015-05-30 01:25:56 +00006183 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006184 reportParseError("frame size not an absolute expression");
6185 return false;
6186 }
6187
6188 if (Parser.getTok().is(AsmToken::Comma))
6189 Parser.Lex();
6190 else {
6191 reportParseError("unexpected token, expected comma");
6192 return false;
6193 }
6194
6195 // Parse the return register.
6196 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006197 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006198 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6199 reportParseError("expected return register");
6200 return false;
6201 }
6202
6203 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6204 if (!ReturnRegOpnd.isGPRAsmReg()) {
6205 reportParseError(ReturnRegOpnd.getStartLoc(),
6206 "expected general purpose register");
6207 return false;
6208 }
6209
6210 // If this is not the end of the statement, report an error.
6211 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6212 reportParseError("unexpected token, expected end of statement");
6213 return false;
6214 }
6215
6216 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6217 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006218 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006219 return false;
6220 }
6221
Jack Carter07c818d2013-01-25 01:31:34 +00006222 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006223 parseDirectiveSet();
6224 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006225 }
6226
Daniel Sandersd97a6342014-08-13 10:07:34 +00006227 if (IDVal == ".mask" || IDVal == ".fmask") {
6228 // .mask bitmask, frame_offset
6229 // bitmask: One bit for each register used.
6230 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6231 // first register is expected to be saved.
6232 // Examples:
6233 // .mask 0x80000000, -4
6234 // .fmask 0x80000000, -4
6235 //
Jack Carterbe332172012-09-07 00:48:02 +00006236
Daniel Sandersd97a6342014-08-13 10:07:34 +00006237 // Parse the bitmask
6238 const MCExpr *BitMask;
6239 int64_t BitMaskVal;
6240
6241 if (Parser.parseExpression(BitMask)) {
6242 reportParseError("expected bitmask value");
6243 return false;
6244 }
6245
Jim Grosbach13760bd2015-05-30 01:25:56 +00006246 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006247 reportParseError("bitmask not an absolute expression");
6248 return false;
6249 }
6250
6251 if (Parser.getTok().is(AsmToken::Comma))
6252 Parser.Lex();
6253 else {
6254 reportParseError("unexpected token, expected comma");
6255 return false;
6256 }
6257
6258 // Parse the frame_offset
6259 const MCExpr *FrameOffset;
6260 int64_t FrameOffsetVal;
6261
6262 if (Parser.parseExpression(FrameOffset)) {
6263 reportParseError("expected frame offset value");
6264 return false;
6265 }
6266
Jim Grosbach13760bd2015-05-30 01:25:56 +00006267 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006268 reportParseError("frame offset not an absolute expression");
6269 return false;
6270 }
6271
6272 // If this is not the end of the statement, report an error.
6273 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6274 reportParseError("unexpected token, expected end of statement");
6275 return false;
6276 }
6277
6278 if (IDVal == ".mask")
6279 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6280 else
6281 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006282 return false;
6283 }
6284
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006285 if (IDVal == ".nan")
6286 return parseDirectiveNaN();
6287
Jack Carter07c818d2013-01-25 01:31:34 +00006288 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006289 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006290 return false;
6291 }
6292
Rafael Espindolab59fb732014-03-28 18:50:26 +00006293 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006294 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006295 return false;
6296 }
6297
Jack Carter07c818d2013-01-25 01:31:34 +00006298 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006299 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006300 return false;
6301 }
6302
Scott Egertond1aeb052016-02-15 16:11:51 +00006303 if (IDVal == ".hword") {
6304 parseDataDirective(2, DirectiveID.getLoc());
6305 return false;
6306 }
6307
Nirav Dave996fc132016-05-05 14:15:46 +00006308 if (IDVal == ".option") {
6309 parseDirectiveOption();
6310 return false;
6311 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006312
6313 if (IDVal == ".abicalls") {
6314 getTargetStreamer().emitDirectiveAbiCalls();
6315 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006316 Error(Parser.getTok().getLoc(),
6317 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006318 // Clear line
6319 Parser.eatToEndOfStatement();
6320 }
6321 return false;
6322 }
6323
Nirav Dave996fc132016-05-05 14:15:46 +00006324 if (IDVal == ".cpsetup") {
6325 parseDirectiveCPSetup();
6326 return false;
6327 }
6328 if (IDVal == ".cpreturn") {
6329 parseDirectiveCPReturn();
6330 return false;
6331 }
6332 if (IDVal == ".module") {
6333 parseDirectiveModule();
6334 return false;
6335 }
6336 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6337 parseInternalDirectiveReallowModule();
6338 return false;
6339 }
6340 if (IDVal == ".insn") {
6341 parseInsnDirective();
6342 return false;
6343 }
6344 if (IDVal == ".sbss") {
6345 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6346 return false;
6347 }
6348 if (IDVal == ".sdata") {
6349 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6350 return false;
6351 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006352
Rafael Espindola870c4e92012-01-11 03:56:41 +00006353 return true;
6354}
6355
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006356bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6357 // If this is not the end of the statement, report an error.
6358 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6359 reportParseError("unexpected token, expected end of statement");
6360 return false;
6361 }
6362
6363 getTargetStreamer().reallowModuleDirective();
6364
6365 getParser().Lex(); // Eat EndOfStatement token.
6366 return false;
6367}
6368
Rafael Espindola870c4e92012-01-11 03:56:41 +00006369extern "C" void LLVMInitializeMipsAsmParser() {
6370 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6371 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6372 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6373 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6374}
Jack Carterb4dbc172012-09-05 23:34:03 +00006375
6376#define GET_REGISTER_MATCHER
6377#define GET_MATCHER_IMPLEMENTATION
6378#include "MipsGenAsmMatcher.inc"