blob: 0291ef929e2c7363504e2cc71976f94d3f46956e [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
Daniel Sandersc5537422016-07-27 13:49:44 +0000132 unsigned
133 checkEarlyTargetMatchPredicate(MCInst &Inst,
134 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000135 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
136
Chad Rosier49963552012-10-13 00:26:04 +0000137 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000138 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000139 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000140 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000141
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000142 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000143 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000144
Toma Tabacu13964452014-09-04 13:23:44 +0000145 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000146
Toma Tabacu13964452014-09-04 13:23:44 +0000147 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000148
David Blaikie960ea3f2014-06-08 16:18:35 +0000149 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
150 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000151
Craig Topper56c590a2014-04-29 07:58:02 +0000152 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000153
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000154 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
155 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000156 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000157 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000158 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
159 SMLoc S);
160 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
161 OperandMatchResultTy parseImm(OperandVector &Operands);
162 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
163 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000164 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
165 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
166 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000167
David Blaikie960ea3f2014-06-08 16:18:35 +0000168 bool searchSymbolAlias(OperandVector &Operands);
169
Toma Tabacu13964452014-09-04 13:23:44 +0000170 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000171
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000172 enum MacroExpanderResultTy {
173 MER_NotAMacro,
174 MER_Success,
175 MER_Fail,
176 };
Jack Carter30a59822012-10-04 04:03:53 +0000177
Matheus Almeida3813d572014-06-19 14:39:14 +0000178 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000179 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
180 MCStreamer &Out,
181 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000182
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000183 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
184 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000185
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000186 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000187 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000188 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000189
Toma Tabacuf712ede2015-06-17 14:31:51 +0000190 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
191 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000192 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000193
Toma Tabacu00e98672015-05-01 12:19:27 +0000194 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000195 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000196
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000197 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
198 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000199 SMLoc IDLoc, MCStreamer &Out,
200 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000201
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000202 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
203 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000204
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000205 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000206 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
207
208 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
209 const MCSubtargetInfo *STI, bool IsImmOpnd);
210
211 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
212 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000213
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000214 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
215 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000216
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000217 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
218 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000219
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000220 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
221 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000222
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000223 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
224 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000225
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000226 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
227 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000228 const bool Signed);
229
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000230 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000231 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000232
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000233 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
234 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000235
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000236 bool expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
237 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000238
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000239 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000240 MCStreamer &Out, const MCSubtargetInfo *STI);
241 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
242 const MCSubtargetInfo *STI);
243 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244 const MCSubtargetInfo *STI);
245 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
246 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000247
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000248 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
249 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000250
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000251 bool reportParseError(Twine ErrorMsg);
252 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000253
Jack Carterb5cf5902013-04-17 00:18:04 +0000254 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000255 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000256
Vladimir Medic4c299852013-11-06 11:27:05 +0000257 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000258
259 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000260 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000261 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000262 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000263 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000264 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000265 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000266 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000267 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000268 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000269 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000270 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000271 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000272 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000273
274 bool parseSetAtDirective();
275 bool parseSetNoAtDirective();
276 bool parseSetMacroDirective();
277 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000278 bool parseSetMsaDirective();
279 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000280 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000281 bool parseSetReorderDirective();
282 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000283 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000284 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000285 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000286 bool parseSetOddSPRegDirective();
287 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000288 bool parseSetPopDirective();
289 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000290 bool parseSetSoftFloatDirective();
291 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000292
Jack Carterd76b2372013-03-21 21:44:16 +0000293 bool parseSetAssignment();
294
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000295 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000296 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000297 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000298 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000299 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000300 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
301 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000302
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000303 bool parseInternalDirectiveReallowModule();
304
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000305 bool eatComma(StringRef ErrorStr);
306
Jack Carter1ac53222013-02-20 23:11:17 +0000307 int matchCPURegisterName(StringRef Symbol);
308
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000309 int matchHWRegsRegisterName(StringRef Symbol);
310
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000311 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000312
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000313 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000314
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000315 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000316
Jack Carter5dc8ac92013-09-25 23:50:44 +0000317 int matchMSA128RegisterName(StringRef Name);
318
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000319 int matchMSA128CtrlRegisterName(StringRef Name);
320
Jack Carterd0bd6422013-04-18 00:41:53 +0000321 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000322
Toma Tabacu89a712b2015-04-15 10:48:56 +0000323 /// Returns the internal register number for the current AT. Also checks if
324 /// the current AT is unavailable (set to $0) and gives an error if it is.
325 /// This should be used in pseudo-instruction expansions which need AT.
326 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000327
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000328 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
329 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000330
331 // Helper function that checks if the value of a vector index is within the
332 // boundaries of accepted values for each RegisterKind
333 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
334 bool validateMSAIndex(int Val, int RegKind);
335
Daniel Sandersf0df2212014-08-04 12:20:00 +0000336 // Selects a new architecture by updating the FeatureBits with the necessary
337 // info including implied dependencies.
338 // Internally, it clears all the feature bits related to *any* architecture
339 // and selects the new one using the ToggleFeature functionality of the
340 // MCSubtargetInfo object that handles implied dependencies. The reason we
341 // clear all the arch related bits manually is because ToggleFeature only
342 // clears the features that imply the feature being cleared and not the
343 // features implied by the feature being cleared. This is easier to see
344 // with an example:
345 // --------------------------------------------------
346 // | Feature | Implies |
347 // | -------------------------------------------------|
348 // | FeatureMips1 | None |
349 // | FeatureMips2 | FeatureMips1 |
350 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
351 // | FeatureMips4 | FeatureMips3 |
352 // | ... | |
353 // --------------------------------------------------
354 //
355 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
356 // FeatureMipsGP64 | FeatureMips1)
357 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
358 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000359 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000360 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000361 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
362 STI.setFeatureBits(FeatureBits);
363 setAvailableFeatures(
364 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000365 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000366 }
367
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000368 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000369 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000370 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000371 setAvailableFeatures(
372 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000373 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000374 }
375 }
376
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000377 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000378 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000379 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000380 setAvailableFeatures(
381 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000382 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000383 }
384 }
385
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000386 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
387 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000388 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000389 }
390
391 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
392 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000393 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000394 }
395
Rafael Espindola870c4e92012-01-11 03:56:41 +0000396public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000397 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000398 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000399 Match_RequiresDifferentOperands,
400 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000401 Match_RequiresSameSrcAndDst,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000402#define GET_OPERAND_DIAGNOSTIC_TYPES
403#include "MipsGenAsmMatcher.inc"
404#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000405 };
406
Akira Hatanakab11ef082015-11-14 06:35:56 +0000407 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000408 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000409 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000410 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
411 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000412 MCAsmParserExtension::Initialize(parser);
413
Toma Tabacu11e14a92015-04-21 11:50:52 +0000414 parser.addAliasForDirective(".asciiz", ".asciz");
415
Jack Carterb4dbc172012-09-05 23:34:03 +0000416 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000417 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000418
Toma Tabacu9db22db2014-09-09 10:15:38 +0000419 // Remember the initial assembler options. The user can not modify these.
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 Sandersa39ef1c2015-08-17 10:11:55 +0000422
Toma Tabacu9db22db2014-09-09 10:15:38 +0000423 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000424 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000425 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000426
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000427 getTargetStreamer().updateABIInfo(*this);
428
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000429 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000430 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000431
432 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000433
Rafael Espindola699281c2016-05-18 11:58:50 +0000434 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000435
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000436 IsCpRestoreSet = false;
437 CpRestoreOffset = -1;
438
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000439 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000440 if ((TheTriple.getArch() == Triple::mips) ||
441 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000442 IsLittleEndian = false;
443 else
444 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000445 }
446
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000447 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
448 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
449
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000450 bool isGP64bit() const {
451 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
452 }
453 bool isFP64bit() const {
454 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
455 }
Eric Christophera5762812015-01-26 17:33:46 +0000456 const MipsABIInfo &getABI() const { return ABI; }
457 bool isABI_N32() const { return ABI.IsN32(); }
458 bool isABI_N64() const { return ABI.IsN64(); }
459 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000460 bool isABI_FPXX() const {
461 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
462 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000463
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000464 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000465 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000466 }
467
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000468 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000469 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000470 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000471 bool hasMips1() const {
472 return getSTI().getFeatureBits()[Mips::FeatureMips1];
473 }
474 bool hasMips2() const {
475 return getSTI().getFeatureBits()[Mips::FeatureMips2];
476 }
477 bool hasMips3() const {
478 return getSTI().getFeatureBits()[Mips::FeatureMips3];
479 }
480 bool hasMips4() const {
481 return getSTI().getFeatureBits()[Mips::FeatureMips4];
482 }
483 bool hasMips5() const {
484 return getSTI().getFeatureBits()[Mips::FeatureMips5];
485 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000486 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000487 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000488 }
489 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000490 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000491 }
492 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000493 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000494 }
495 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000496 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 }
Daniel Sanders17793142015-02-18 16:24:50 +0000498 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000500 }
501 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000502 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000503 }
504 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000505 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000506 }
507 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000508 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000509 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000510 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000511 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000512 }
513 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000514 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000515 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000516
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000517 bool hasDSP() const {
518 return getSTI().getFeatureBits()[Mips::FeatureDSP];
519 }
520 bool hasDSPR2() const {
521 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
522 }
523 bool hasDSPR3() const {
524 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
525 }
526 bool hasMSA() const {
527 return getSTI().getFeatureBits()[Mips::FeatureMSA];
528 }
Kai Nackee0245392015-01-27 19:11:28 +0000529 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000530 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000531 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000532
Daniel Sandersa6994442015-08-18 12:33:54 +0000533 bool inPicMode() {
534 return IsPicEnabled;
535 }
536
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000537 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000538 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000539 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000540
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000541 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000542 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000543 }
544
Eric Christophere8ae3e32015-05-07 23:10:21 +0000545 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000546 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000547 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000548
Toma Tabacud9d344b2015-04-27 14:05:04 +0000549 /// Warn if RegIndex is the same as the current AT.
550 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000551
552 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000553
554 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000555};
556}
557
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000558namespace {
559
560/// MipsOperand - Instances of this class represent a parsed Mips machine
561/// instruction.
562class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000563public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000564 /// Broad categories of register classes
565 /// The exact class is finalized by the render method.
566 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000567 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000568 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000569 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000570 RegKind_FCC = 4, /// FCC
571 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
572 RegKind_MSACtrl = 16, /// MSA control registers
573 RegKind_COP2 = 32, /// COP2
574 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
575 /// context).
576 RegKind_CCR = 128, /// CCR
577 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000578 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000579 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000580 /// Potentially any (e.g. $1)
581 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
582 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000583 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000584 };
585
586private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000587 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000588 k_Immediate, /// An immediate (possibly involving symbol references)
589 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000590 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000591 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000592 k_RegList, /// A physical register list
593 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000594 } Kind;
595
David Blaikie960ea3f2014-06-08 16:18:35 +0000596public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000597 MipsOperand(KindTy K, MipsAsmParser &Parser)
598 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
599
David Blaikie960ea3f2014-06-08 16:18:35 +0000600private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000601 /// For diagnostics, and checking the assembler temporary
602 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000603
Eric Christopher8996c5d2013-03-15 00:42:55 +0000604 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000605 const char *Data;
606 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000607 };
608
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000609 struct RegIdxOp {
610 unsigned Index; /// Index into the register class
611 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000612 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000613 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000614 };
615
616 struct ImmOp {
617 const MCExpr *Val;
618 };
619
620 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000621 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000622 const MCExpr *Off;
623 };
624
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000625 struct RegListOp {
626 SmallVector<unsigned, 10> *List;
627 };
628
Jack Carterb4dbc172012-09-05 23:34:03 +0000629 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000630 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000631 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000632 struct ImmOp Imm;
633 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000634 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000635 };
636
637 SMLoc StartLoc, EndLoc;
638
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000639 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000640 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
641 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000642 const MCRegisterInfo *RegInfo,
643 SMLoc S, SMLoc E,
644 MipsAsmParser &Parser) {
645 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000646 Op->RegIdx.Index = Index;
647 Op->RegIdx.RegInfo = RegInfo;
648 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000649 Op->RegIdx.Tok.Data = Str.data();
650 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000651 Op->StartLoc = S;
652 Op->EndLoc = E;
653 return Op;
654 }
655
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000656public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000657 /// Coerce the register to GPR32 and return the real register for the current
658 /// target.
659 unsigned getGPR32Reg() const {
660 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000661 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000662 unsigned ClassID = Mips::GPR32RegClassID;
663 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000664 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000665
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000666 /// Coerce the register to GPR32 and return the real register for the current
667 /// target.
668 unsigned getGPRMM16Reg() const {
669 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
670 unsigned ClassID = Mips::GPR32RegClassID;
671 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
672 }
673
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000674 /// Coerce the register to GPR64 and return the real register for the current
675 /// target.
676 unsigned getGPR64Reg() const {
677 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
678 unsigned ClassID = Mips::GPR64RegClassID;
679 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000680 }
681
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000682private:
683 /// Coerce the register to AFGR64 and return the real register for the current
684 /// target.
685 unsigned getAFGR64Reg() const {
686 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
687 if (RegIdx.Index % 2 != 0)
688 AsmParser.Warning(StartLoc, "Float register should be even.");
689 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
690 .getRegister(RegIdx.Index / 2);
691 }
692
693 /// Coerce the register to FGR64 and return the real register for the current
694 /// target.
695 unsigned getFGR64Reg() const {
696 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
697 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
698 .getRegister(RegIdx.Index);
699 }
700
701 /// Coerce the register to FGR32 and return the real register for the current
702 /// target.
703 unsigned getFGR32Reg() const {
704 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
705 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
706 .getRegister(RegIdx.Index);
707 }
708
709 /// Coerce the register to FGRH32 and return the real register for the current
710 /// target.
711 unsigned getFGRH32Reg() const {
712 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
713 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
714 .getRegister(RegIdx.Index);
715 }
716
717 /// Coerce the register to FCC and return the real register for the current
718 /// target.
719 unsigned getFCCReg() const {
720 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
721 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
722 .getRegister(RegIdx.Index);
723 }
724
725 /// Coerce the register to MSA128 and return the real register for the current
726 /// target.
727 unsigned getMSA128Reg() const {
728 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
729 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
730 // identical
731 unsigned ClassID = Mips::MSA128BRegClassID;
732 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
733 }
734
735 /// Coerce the register to MSACtrl and return the real register for the
736 /// current target.
737 unsigned getMSACtrlReg() const {
738 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
739 unsigned ClassID = Mips::MSACtrlRegClassID;
740 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
741 }
742
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000743 /// Coerce the register to COP0 and return the real register for the
744 /// current target.
745 unsigned getCOP0Reg() const {
746 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
747 unsigned ClassID = Mips::COP0RegClassID;
748 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
749 }
750
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000751 /// Coerce the register to COP2 and return the real register for the
752 /// current target.
753 unsigned getCOP2Reg() const {
754 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
755 unsigned ClassID = Mips::COP2RegClassID;
756 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
757 }
758
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000759 /// Coerce the register to COP3 and return the real register for the
760 /// current target.
761 unsigned getCOP3Reg() const {
762 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
763 unsigned ClassID = Mips::COP3RegClassID;
764 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
765 }
766
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000767 /// Coerce the register to ACC64DSP and return the real register for the
768 /// current target.
769 unsigned getACC64DSPReg() const {
770 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
771 unsigned ClassID = Mips::ACC64DSPRegClassID;
772 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
773 }
774
775 /// Coerce the register to HI32DSP and return the real register for the
776 /// current target.
777 unsigned getHI32DSPReg() const {
778 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
779 unsigned ClassID = Mips::HI32DSPRegClassID;
780 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
781 }
782
783 /// Coerce the register to LO32DSP and return the real register for the
784 /// current target.
785 unsigned getLO32DSPReg() const {
786 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
787 unsigned ClassID = Mips::LO32DSPRegClassID;
788 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
789 }
790
791 /// Coerce the register to CCR and return the real register for the
792 /// current target.
793 unsigned getCCRReg() const {
794 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
795 unsigned ClassID = Mips::CCRRegClassID;
796 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
797 }
798
799 /// Coerce the register to HWRegs and return the real register for the
800 /// current target.
801 unsigned getHWRegsReg() const {
802 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
803 unsigned ClassID = Mips::HWRegsRegClassID;
804 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
805 }
806
807public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000808 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000809 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000810 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000811 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000812 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000813 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000814 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000815 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000816 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000817
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000818 void addRegOperands(MCInst &Inst, unsigned N) const {
819 llvm_unreachable("Use a custom parser instead");
820 }
821
Daniel Sanders21bce302014-04-01 12:35:23 +0000822 /// Render the operand to an MCInst as a GPR32
823 /// Asserts if the wrong number of operands are requested, or the operand
824 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000825 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
826 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000827 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000828 }
829
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000830 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
831 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000832 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000833 }
834
Jozef Kolek1904fa22014-11-24 14:25:53 +0000835 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
836 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000837 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000838 }
839
Zoran Jovanovic41688672015-02-10 16:36:20 +0000840 void addGPRMM16AsmRegMovePOperands(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(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000843 }
844
Daniel Sanders21bce302014-04-01 12:35:23 +0000845 /// Render the operand to an MCInst as a GPR64
846 /// Asserts if the wrong number of operands are requested, or the operand
847 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000848 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
849 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000850 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000851 }
852
853 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
854 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000855 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000856 }
857
858 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
859 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000860 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000861 }
862
863 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
864 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000865 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000866 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000867 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000868 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
869 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000870 }
871
872 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
873 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000874 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000875 }
876
877 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
878 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000879 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000880 }
881
882 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
883 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000884 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000885 }
886
887 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
888 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000889 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000890 }
891
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000892 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
893 assert(N == 1 && "Invalid number of operands!");
894 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
895 }
896
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000897 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
898 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000899 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000900 }
901
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000902 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
903 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000904 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000905 }
906
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000907 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
908 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000909 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000910 }
911
912 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
913 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000914 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000915 }
916
917 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
918 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000919 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000920 }
921
922 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
923 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000924 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000925 }
926
927 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
928 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000929 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000930 }
931
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000932 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000933 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
934 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000935 uint64_t Imm = getConstantImm() - Offset;
936 Imm &= (1 << Bits) - 1;
937 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000938 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000939 Inst.addOperand(MCOperand::createImm(Imm));
940 }
941
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000942 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +0000943 void addSImmOperands(MCInst &Inst, unsigned N) const {
944 if (isImm() && !isConstantImm()) {
945 addExpr(Inst, getImm());
946 return;
947 }
948 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
949 }
950
951 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000952 void addUImmOperands(MCInst &Inst, unsigned N) const {
953 if (isImm() && !isConstantImm()) {
954 addExpr(Inst, getImm());
955 return;
956 }
957 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
958 }
959
Daniel Sanders78e89022016-03-11 11:37:50 +0000960 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
961 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
962 assert(N == 1 && "Invalid number of operands!");
963 int64_t Imm = getConstantImm() - Offset;
964 Imm = SignExtend64<Bits>(Imm);
965 Imm += Offset;
966 Imm += AdjustOffset;
967 Inst.addOperand(MCOperand::createImm(Imm));
968 }
969
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000970 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000971 assert(N == 1 && "Invalid number of operands!");
972 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000973 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000974 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000975
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000976 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000977 assert(N == 2 && "Invalid number of operands!");
978
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000979 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
980 ? getMemBase()->getGPR64Reg()
981 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000982
983 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000984 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000985 }
986
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000987 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
988 assert(N == 2 && "Invalid number of operands!");
989
Jim Grosbache9119e42015-05-13 18:37:00 +0000990 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000991
992 const MCExpr *Expr = getMemOff();
993 addExpr(Inst, Expr);
994 }
995
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000996 void addRegListOperands(MCInst &Inst, unsigned N) const {
997 assert(N == 1 && "Invalid number of operands!");
998
999 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001000 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001001 }
1002
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001003 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1004 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001005 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001006 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001007 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1008 Inst.addOperand(MCOperand::createReg(
1009 RegIdx.RegInfo->getRegClass(
1010 AsmParser.getABI().AreGprs64bit()
1011 ? Mips::GPR64RegClassID
1012 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1013 Inst.addOperand(MCOperand::createReg(
1014 RegIdx.RegInfo->getRegClass(
1015 AsmParser.getABI().AreGprs64bit()
1016 ? Mips::GPR64RegClassID
1017 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001018 }
1019
Zoran Jovanovic41688672015-02-10 16:36:20 +00001020 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1021 assert(N == 2 && "Invalid number of operands!");
1022 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001023 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001024 }
1025
Craig Topper56c590a2014-04-29 07:58:02 +00001026 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001027 // As a special case until we sort out the definition of div/divu, accept
1028 // $0/$zero here so that MCK_ZERO works correctly.
1029 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001030 }
1031 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001032 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001033 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +00001034 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001035 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001036 bool isConstantImmz() const {
1037 return isConstantImm() && getConstantImm() == 0;
1038 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001039 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1040 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1041 }
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001042 template <unsigned Bits> bool isSImm() const {
1043 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1044 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001045 template <unsigned Bits> bool isUImm() const {
1046 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1047 }
1048 template <unsigned Bits> bool isAnyImm() const {
1049 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1050 isUInt<Bits>(getConstantImm()))
1051 : isImm();
1052 }
Daniel Sanders78e89022016-03-11 11:37:50 +00001053 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1054 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001055 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001056 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1057 return isConstantImm() && getConstantImm() >= Bottom &&
1058 getConstantImm() <= Top;
1059 }
Craig Topper56c590a2014-04-29 07:58:02 +00001060 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001061 // Note: It's not possible to pretend that other operand kinds are tokens.
1062 // The matcher emitter checks tokens first.
1063 return Kind == k_Token;
1064 }
Craig Topper56c590a2014-04-29 07:58:02 +00001065 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001066 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001067 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001068 }
Simon Dardis4ccda502016-05-27 13:56:36 +00001069 // Allow relocation operators.
1070 // FIXME: This predicate and others need to look through binary expressions
1071 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001072 template <unsigned Bits, unsigned ShiftAmount = 0>
1073 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001074 if (!isMem())
1075 return false;
1076 if (!getMemBase()->isGPRAsmReg())
1077 return false;
1078 if (isa<MCTargetExpr>(getMemOff()) ||
1079 (isConstantMemOff() &&
1080 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1081 return true;
1082 MCValue Res;
1083 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1084 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001085 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001086 bool isMemWithGRPMM16Base() const {
1087 return isMem() && getMemBase()->isMM16AsmReg();
1088 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001089 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1090 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1091 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1092 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001093 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1094 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1095 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1096 && (getMemBase()->getGPR32Reg() == Mips::SP);
1097 }
Daniel Sanderse473dc92016-05-09 13:38:25 +00001098 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1099 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1100 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1101 && (getMemBase()->getGPR32Reg() == Mips::GP);
1102 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001103 template <unsigned Bits, unsigned ShiftLeftAmount>
1104 bool isScaledUImm() const {
1105 return isConstantImm() &&
1106 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001107 }
Daniel Sanders97297772016-03-22 14:40:00 +00001108 template <unsigned Bits, unsigned ShiftLeftAmount>
1109 bool isScaledSImm() const {
1110 return isConstantImm() &&
1111 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
1112 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001113 bool isRegList16() const {
1114 if (!isRegList())
1115 return false;
1116
1117 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001118 if (Size < 2 || Size > 5)
1119 return false;
1120
1121 unsigned R0 = RegList.List->front();
1122 unsigned R1 = RegList.List->back();
1123 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1124 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001125 return false;
1126
1127 int PrevReg = *RegList.List->begin();
1128 for (int i = 1; i < Size - 1; i++) {
1129 int Reg = (*(RegList.List))[i];
1130 if ( Reg != PrevReg + 1)
1131 return false;
1132 PrevReg = Reg;
1133 }
1134
1135 return true;
1136 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001137 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001138 bool isLSAImm() const {
1139 if (!isConstantImm())
1140 return false;
1141 int64_t Val = getConstantImm();
1142 return 1 <= Val && Val <= 4;
1143 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001144 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001145 bool isMovePRegPair() const {
1146 if (Kind != k_RegList || RegList.List->size() != 2)
1147 return false;
1148
1149 unsigned R0 = RegList.List->front();
1150 unsigned R1 = RegList.List->back();
1151
1152 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1153 (R0 == Mips::A1 && R1 == Mips::A3) ||
1154 (R0 == Mips::A2 && R1 == Mips::A3) ||
1155 (R0 == Mips::A0 && R1 == Mips::S5) ||
1156 (R0 == Mips::A0 && R1 == Mips::S6) ||
1157 (R0 == Mips::A0 && R1 == Mips::A1) ||
1158 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001159 (R0 == Mips::A0 && R1 == Mips::A3) ||
1160 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1161 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1162 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1163 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1164 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1165 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1166 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1167 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001168 return true;
1169
1170 return false;
1171 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001172
1173 StringRef getToken() const {
1174 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001175 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001176 }
Zlatko Buljanba553a62016-05-09 08:07:28 +00001177 bool isRegPair() const {
1178 return Kind == k_RegPair && RegIdx.Index <= 30;
1179 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001180
Craig Topper56c590a2014-04-29 07:58:02 +00001181 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001182 // As a special case until we sort out the definition of div/divu, accept
1183 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001184 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1185 RegIdx.Kind & RegKind_GPR)
1186 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001187
Daniel Sanders976d9382016-07-05 13:38:40 +00001188 llvm_unreachable("Invalid access!");
1189 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001190 }
1191
Jack Carterb4dbc172012-09-05 23:34:03 +00001192 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001193 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001194 return Imm.Val;
1195 }
1196
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001197 int64_t getConstantImm() const {
1198 const MCExpr *Val = getImm();
1199 return static_cast<const MCConstantExpr *>(Val)->getValue();
1200 }
1201
1202 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001203 assert((Kind == k_Memory) && "Invalid access!");
1204 return Mem.Base;
1205 }
1206
1207 const MCExpr *getMemOff() const {
1208 assert((Kind == k_Memory) && "Invalid access!");
1209 return Mem.Off;
1210 }
1211
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001212 int64_t getConstantMemOff() const {
1213 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1214 }
1215
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001216 const SmallVectorImpl<unsigned> &getRegList() const {
1217 assert((Kind == k_RegList) && "Invalid access!");
1218 return *(RegList.List);
1219 }
1220
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001221 unsigned getRegPair() const {
1222 assert((Kind == k_RegPair) && "Invalid access!");
1223 return RegIdx.Index;
1224 }
1225
David Blaikie960ea3f2014-06-08 16:18:35 +00001226 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1227 MipsAsmParser &Parser) {
1228 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001229 Op->Tok.Data = Str.data();
1230 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001231 Op->StartLoc = S;
1232 Op->EndLoc = S;
1233 return Op;
1234 }
1235
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001236 /// Create a numeric register (e.g. $1). The exact register remains
1237 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001238 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001239 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1240 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001241 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001242 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001243 }
1244
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001245 /// Create a register that is definitely a GPR.
1246 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001247 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001248 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1249 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1250 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001251 }
1252
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001253 /// Create a register that is definitely a FGR.
1254 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001255 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001256 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1257 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1258 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001259 }
1260
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001261 /// Create a register that is definitely a HWReg.
1262 /// This is typically only used for named registers such as $hwr_cpunum.
1263 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001264 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001265 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001266 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001267 }
1268
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001269 /// Create a register that is definitely an FCC.
1270 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001271 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001272 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1273 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1274 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001275 }
1276
1277 /// Create a register that is definitely an ACC.
1278 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001279 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001280 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1281 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1282 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001283 }
1284
1285 /// Create a register that is definitely an MSA128.
1286 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001287 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001288 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1289 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1290 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001291 }
1292
1293 /// Create a register that is definitely an MSACtrl.
1294 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001295 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001296 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1297 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1298 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001299 }
1300
David Blaikie960ea3f2014-06-08 16:18:35 +00001301 static std::unique_ptr<MipsOperand>
1302 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1303 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001304 Op->Imm.Val = Val;
1305 Op->StartLoc = S;
1306 Op->EndLoc = E;
1307 return Op;
1308 }
1309
David Blaikie960ea3f2014-06-08 16:18:35 +00001310 static std::unique_ptr<MipsOperand>
1311 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1312 SMLoc E, MipsAsmParser &Parser) {
1313 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1314 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001315 Op->Mem.Off = Off;
1316 Op->StartLoc = S;
1317 Op->EndLoc = E;
1318 return Op;
1319 }
1320
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001321 static std::unique_ptr<MipsOperand>
1322 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1323 MipsAsmParser &Parser) {
1324 assert (Regs.size() > 0 && "Empty list not allowed");
1325
1326 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001327 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001328 Op->StartLoc = StartLoc;
1329 Op->EndLoc = EndLoc;
1330 return Op;
1331 }
1332
Daniel Sandersd044e492016-05-09 13:10:57 +00001333 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1334 SMLoc S, SMLoc E,
1335 MipsAsmParser &Parser) {
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001336 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001337 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001338 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1339 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001340 Op->StartLoc = S;
1341 Op->EndLoc = E;
1342 return Op;
1343 }
1344
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001345 bool isGPRAsmReg() const {
1346 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001347 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001348 bool isMM16AsmReg() const {
1349 if (!(isRegIdx() && RegIdx.Kind))
1350 return false;
1351 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1352 || RegIdx.Index == 16 || RegIdx.Index == 17);
1353 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001354 bool isMM16AsmRegZero() const {
1355 if (!(isRegIdx() && RegIdx.Kind))
1356 return false;
1357 return (RegIdx.Index == 0 ||
1358 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1359 RegIdx.Index == 17);
1360 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001361 bool isMM16AsmRegMoveP() const {
1362 if (!(isRegIdx() && RegIdx.Kind))
1363 return false;
1364 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1365 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1366 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001367 bool isFGRAsmReg() const {
1368 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1369 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001370 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001371 bool isHWRegsAsmReg() const {
1372 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001373 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001374 bool isCCRAsmReg() const {
1375 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001376 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001377 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001378 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1379 return false;
1380 if (!AsmParser.hasEightFccRegisters())
1381 return RegIdx.Index == 0;
1382 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001383 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001384 bool isACCAsmReg() const {
1385 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001386 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001387 bool isCOP0AsmReg() const {
1388 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1389 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001390 bool isCOP2AsmReg() const {
1391 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001392 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001393 bool isCOP3AsmReg() const {
1394 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1395 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001396 bool isMSA128AsmReg() const {
1397 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001398 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001399 bool isMSACtrlAsmReg() const {
1400 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001401 }
1402
Jack Carterb4dbc172012-09-05 23:34:03 +00001403 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001404 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001405 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001406 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001407
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001408 virtual ~MipsOperand() {
1409 switch (Kind) {
1410 case k_Immediate:
1411 break;
1412 case k_Memory:
1413 delete Mem.Base;
1414 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001415 case k_RegList:
1416 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001417 case k_RegisterIndex:
1418 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001419 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001420 break;
1421 }
1422 }
1423
Craig Topper56c590a2014-04-29 07:58:02 +00001424 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001425 switch (Kind) {
1426 case k_Immediate:
1427 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001428 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001429 OS << ">";
1430 break;
1431 case k_Memory:
1432 OS << "Mem<";
1433 Mem.Base->print(OS);
1434 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001435 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001436 OS << ">";
1437 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001438 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001439 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1440 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001441 break;
1442 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001443 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001444 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001445 case k_RegList:
1446 OS << "RegList< ";
1447 for (auto Reg : (*RegList.List))
1448 OS << Reg << " ";
1449 OS << ">";
1450 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001451 case k_RegPair:
1452 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1453 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001454 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001455 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001456
1457 bool isValidForTie(const MipsOperand &Other) const {
1458 if (Kind != Other.Kind)
1459 return false;
1460
1461 switch (Kind) {
1462 default:
1463 llvm_unreachable("Unexpected kind");
1464 return false;
1465 case k_RegisterIndex: {
1466 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1467 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1468 return Token == OtherToken;
1469 }
1470 }
1471 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001472}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001473} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001474
Jack Carter9e65aa32013-03-22 00:05:30 +00001475namespace llvm {
1476extern const MCInstrDesc MipsInsts[];
1477}
1478static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1479 return MipsInsts[Opcode];
1480}
1481
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001482static bool hasShortDelaySlot(unsigned Opcode) {
1483 switch (Opcode) {
1484 case Mips::JALS_MM:
1485 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001486 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001487 case Mips::BGEZALS_MM:
1488 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001489 return true;
1490 default:
1491 return false;
1492 }
1493}
1494
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001495static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1496 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1497 return &SRExpr->getSymbol();
1498 }
1499
1500 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1501 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1502 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1503
1504 if (LHSSym)
1505 return LHSSym;
1506
1507 if (RHSSym)
1508 return RHSSym;
1509
1510 return nullptr;
1511 }
1512
1513 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1514 return getSingleMCSymbol(UExpr->getSubExpr());
1515
1516 return nullptr;
1517}
1518
1519static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1520 if (isa<MCSymbolRefExpr>(Expr))
1521 return 1;
1522
1523 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1524 return countMCSymbolRefExpr(BExpr->getLHS()) +
1525 countMCSymbolRefExpr(BExpr->getRHS());
1526
1527 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1528 return countMCSymbolRefExpr(UExpr->getSubExpr());
1529
1530 return 0;
1531}
1532
Jack Carter9e65aa32013-03-22 00:05:30 +00001533bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001534 MCStreamer &Out,
1535 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001536 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001537 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001538 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001539
Jack Carter9e65aa32013-03-22 00:05:30 +00001540 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001541
1542 if (MCID.isBranch() || MCID.isCall()) {
1543 const unsigned Opcode = Inst.getOpcode();
1544 MCOperand Offset;
1545
1546 switch (Opcode) {
1547 default:
1548 break;
Kai Nackee0245392015-01-27 19:11:28 +00001549 case Mips::BBIT0:
1550 case Mips::BBIT032:
1551 case Mips::BBIT1:
1552 case Mips::BBIT132:
1553 assert(hasCnMips() && "instruction only valid for octeon cpus");
1554 // Fall through
1555
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001556 case Mips::BEQ:
1557 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001558 case Mips::BEQ_MM:
1559 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001560 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001561 Offset = Inst.getOperand(2);
1562 if (!Offset.isImm())
1563 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001564 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001565 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001566 if (OffsetToAlignment(Offset.getImm(),
1567 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001568 return Error(IDLoc, "branch to misaligned address");
1569 break;
1570 case Mips::BGEZ:
1571 case Mips::BGTZ:
1572 case Mips::BLEZ:
1573 case Mips::BLTZ:
1574 case Mips::BGEZAL:
1575 case Mips::BLTZAL:
1576 case Mips::BC1F:
1577 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001578 case Mips::BGEZ_MM:
1579 case Mips::BGTZ_MM:
1580 case Mips::BLEZ_MM:
1581 case Mips::BLTZ_MM:
1582 case Mips::BGEZAL_MM:
1583 case Mips::BLTZAL_MM:
1584 case Mips::BC1F_MM:
1585 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001586 case Mips::BC1EQZC_MMR6:
1587 case Mips::BC1NEZC_MMR6:
1588 case Mips::BC2EQZC_MMR6:
1589 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001590 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001591 Offset = Inst.getOperand(1);
1592 if (!Offset.isImm())
1593 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001594 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001595 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001596 if (OffsetToAlignment(Offset.getImm(),
1597 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001598 return Error(IDLoc, "branch to misaligned address");
1599 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001600 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001601 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001602 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001603 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001604 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1605 Offset = Inst.getOperand(1);
1606 if (!Offset.isImm())
1607 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001608 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001609 return Error(IDLoc, "branch target out of range");
1610 if (OffsetToAlignment(Offset.getImm(), 2LL))
1611 return Error(IDLoc, "branch to misaligned address");
1612 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001613 }
1614 }
1615
Daniel Sandersa84989a2014-06-16 13:25:35 +00001616 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1617 // We still accept it but it is a normal nop.
1618 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1619 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1620 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1621 "nop instruction");
1622 }
1623
Kai Nackee0245392015-01-27 19:11:28 +00001624 if (hasCnMips()) {
1625 const unsigned Opcode = Inst.getOpcode();
1626 MCOperand Opnd;
1627 int Imm;
1628
1629 switch (Opcode) {
1630 default:
1631 break;
1632
1633 case Mips::BBIT0:
1634 case Mips::BBIT032:
1635 case Mips::BBIT1:
1636 case Mips::BBIT132:
1637 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1638 // The offset is handled above
1639 Opnd = Inst.getOperand(1);
1640 if (!Opnd.isImm())
1641 return Error(IDLoc, "expected immediate operand kind");
1642 Imm = Opnd.getImm();
1643 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1644 Opcode == Mips::BBIT1 ? 63 : 31))
1645 return Error(IDLoc, "immediate operand value out of range");
1646 if (Imm > 31) {
1647 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1648 : Mips::BBIT132);
1649 Inst.getOperand(1).setImm(Imm - 32);
1650 }
1651 break;
1652
Kai Nackee0245392015-01-27 19:11:28 +00001653 case Mips::SEQi:
1654 case Mips::SNEi:
1655 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1656 Opnd = Inst.getOperand(2);
1657 if (!Opnd.isImm())
1658 return Error(IDLoc, "expected immediate operand kind");
1659 Imm = Opnd.getImm();
1660 if (!isInt<10>(Imm))
1661 return Error(IDLoc, "immediate operand value out of range");
1662 break;
1663 }
1664 }
1665
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001666 // This expansion is not in a function called by tryExpandInstruction()
1667 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001668 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1669 inPicMode()) {
1670 warnIfNoMacro(IDLoc);
1671
1672 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1673
1674 // We can do this expansion if there's only 1 symbol in the argument
1675 // expression.
1676 if (countMCSymbolRefExpr(JalExpr) > 1)
1677 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1678
1679 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001680 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001681 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1682
1683 // FIXME: Add support for label+offset operands (currently causes an error).
1684 // FIXME: Add support for forward-declared local symbols.
1685 // FIXME: Add expansion for when the LargeGOT option is enabled.
1686 if (JalSym->isInSection() || JalSym->isTemporary()) {
1687 if (isABI_O32()) {
1688 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001689 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001690 // R_(MICRO)MIPS_GOT16 label
1691 // addiu $25, $25, 0
1692 // R_(MICRO)MIPS_LO16 label
1693 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001694 const MCExpr *Got16RelocExpr =
1695 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1696 const MCExpr *Lo16RelocExpr =
1697 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001698
Daniel Sandersa736b372016-04-29 13:33:12 +00001699 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1700 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1701 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1702 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001703 } else if (isABI_N32() || isABI_N64()) {
1704 // If it's a local symbol and the N32/N64 ABIs are being used,
1705 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001706 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001707 // R_(MICRO)MIPS_GOT_DISP label
1708 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001709 const MCExpr *GotDispRelocExpr =
1710 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001711
Daniel Sandersa736b372016-04-29 13:33:12 +00001712 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1713 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1714 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001715 }
1716 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001717 // If it's an external/weak symbol, we expand to:
1718 // lw/ld $25, 0($gp)
1719 // R_(MICRO)MIPS_CALL16 label
1720 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001721 const MCExpr *Call16RelocExpr =
1722 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001723
Daniel Sandersa736b372016-04-29 13:33:12 +00001724 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1725 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001726 }
1727
1728 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001729 if (IsCpRestoreSet && inMicroMipsMode())
1730 JalrInst.setOpcode(Mips::JALRS_MM);
1731 else
1732 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001733 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1734 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1735
1736 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1737 // This relocation is supposed to be an optimization hint for the linker
1738 // and is not necessary for correctness.
1739
1740 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001741 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001742 }
1743
Jack Carter9e65aa32013-03-22 00:05:30 +00001744 if (MCID.mayLoad() || MCID.mayStore()) {
1745 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001746 // reference or immediate we may have to expand instructions.
1747 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001748 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001749 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1750 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001751 MCOperand &Op = Inst.getOperand(i);
1752 if (Op.isImm()) {
1753 int MemOffset = Op.getImm();
1754 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001755 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001756 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001757 return false;
1758 }
1759 } else if (Op.isExpr()) {
1760 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001761 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001762 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001763 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001764 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001765 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001766 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001767 return false;
1768 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001769 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001770 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001771 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001772 }
1773 }
1774 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001775 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001776 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001777
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001778 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001779 if (MCID.mayLoad()) {
1780 // Try to create 16-bit GP relative load instruction.
1781 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1782 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1783 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1784 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1785 MCOperand &Op = Inst.getOperand(i);
1786 if (Op.isImm()) {
1787 int MemOffset = Op.getImm();
1788 MCOperand &DstReg = Inst.getOperand(0);
1789 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001790 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001791 getContext().getRegisterInfo()->getRegClass(
1792 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001793 (BaseReg.getReg() == Mips::GP ||
1794 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001795
Daniel Sandersa736b372016-04-29 13:33:12 +00001796 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1797 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001798 return false;
1799 }
1800 }
1801 }
1802 } // for
1803 } // if load
1804
1805 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1806
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001807 MCOperand Opnd;
1808 int Imm;
1809
1810 switch (Inst.getOpcode()) {
1811 default:
1812 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001813 case Mips::ADDIUSP_MM:
1814 Opnd = Inst.getOperand(0);
1815 if (!Opnd.isImm())
1816 return Error(IDLoc, "expected immediate operand kind");
1817 Imm = Opnd.getImm();
1818 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1819 Imm % 4 != 0)
1820 return Error(IDLoc, "immediate operand value out of range");
1821 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001822 case Mips::SLL16_MM:
1823 case Mips::SRL16_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 < 1 || Imm > 8)
1829 return Error(IDLoc, "immediate operand value out of range");
1830 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001831 case Mips::LI16_MM:
1832 Opnd = Inst.getOperand(1);
1833 if (!Opnd.isImm())
1834 return Error(IDLoc, "expected immediate operand kind");
1835 Imm = Opnd.getImm();
1836 if (Imm < -1 || Imm > 126)
1837 return Error(IDLoc, "immediate operand value out of range");
1838 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001839 case Mips::ADDIUR2_MM:
1840 Opnd = Inst.getOperand(2);
1841 if (!Opnd.isImm())
1842 return Error(IDLoc, "expected immediate operand kind");
1843 Imm = Opnd.getImm();
1844 if (!(Imm == 1 || Imm == -1 ||
1845 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1846 return Error(IDLoc, "immediate operand value out of range");
1847 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001848 case Mips::ANDI16_MM:
1849 Opnd = Inst.getOperand(2);
1850 if (!Opnd.isImm())
1851 return Error(IDLoc, "expected immediate operand kind");
1852 Imm = Opnd.getImm();
1853 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1854 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1855 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1856 return Error(IDLoc, "immediate operand value out of range");
1857 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001858 case Mips::LBU16_MM:
1859 Opnd = Inst.getOperand(2);
1860 if (!Opnd.isImm())
1861 return Error(IDLoc, "expected immediate operand kind");
1862 Imm = Opnd.getImm();
1863 if (Imm < -1 || Imm > 14)
1864 return Error(IDLoc, "immediate operand value out of range");
1865 break;
1866 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001867 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001868 Opnd = Inst.getOperand(2);
1869 if (!Opnd.isImm())
1870 return Error(IDLoc, "expected immediate operand kind");
1871 Imm = Opnd.getImm();
1872 if (Imm < 0 || Imm > 15)
1873 return Error(IDLoc, "immediate operand value out of range");
1874 break;
1875 case Mips::LHU16_MM:
1876 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001877 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001878 Opnd = Inst.getOperand(2);
1879 if (!Opnd.isImm())
1880 return Error(IDLoc, "expected immediate operand kind");
1881 Imm = Opnd.getImm();
1882 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1883 return Error(IDLoc, "immediate operand value out of range");
1884 break;
1885 case Mips::LW16_MM:
1886 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001887 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001888 Opnd = Inst.getOperand(2);
1889 if (!Opnd.isImm())
1890 return Error(IDLoc, "expected immediate operand kind");
1891 Imm = Opnd.getImm();
1892 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1893 return Error(IDLoc, "immediate operand value out of range");
1894 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001895 case Mips::ADDIUPC_MM:
1896 MCOperand Opnd = Inst.getOperand(1);
1897 if (!Opnd.isImm())
1898 return Error(IDLoc, "expected immediate operand kind");
1899 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001900 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001901 return Error(IDLoc, "immediate operand value out of range");
1902 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001903 }
1904 }
1905
Daniel Sandersd8c07762016-04-18 12:35:36 +00001906 bool FillDelaySlot =
1907 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
1908 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00001909 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001910
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001911 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001912 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001913 switch (ExpandResult) {
1914 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001915 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001916 break;
1917 case MER_Success:
1918 break;
1919 case MER_Fail:
1920 return true;
1921 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001922
Daniel Sanderscda908a2016-05-16 09:10:13 +00001923 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
1924 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
1925 if (inMicroMipsMode())
1926 TOut.setUsesMicroMips();
1927
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001928 // If this instruction has a delay slot and .set reorder is active,
1929 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00001930 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001931 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
1932 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001933 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001934
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001935 if ((Inst.getOpcode() == Mips::JalOneReg ||
1936 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1937 isPicAndNotNxxAbi()) {
1938 if (IsCpRestoreSet) {
1939 // We need a NOP between the JALR and the LW:
1940 // If .set reorder has been used, we've already emitted a NOP.
1941 // If .set noreorder has been used, we need to emit a NOP at this point.
1942 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00001943 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
1944 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001945
1946 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00001947 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001948 } else
1949 Warning(IDLoc, "no .cprestore used in PIC mode");
1950 }
1951
Jack Carter9e65aa32013-03-22 00:05:30 +00001952 return false;
1953}
1954
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001955MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001956MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
1957 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001958 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001959 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001960 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001961 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001962 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001963 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001964 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001965 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001966 case Mips::LoadAddrImm64:
1967 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1968 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1969 "expected immediate operand kind");
1970
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001971 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1972 Inst.getOperand(1),
1973 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001974 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001975 ? MER_Fail
1976 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001977 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001978 case Mips::LoadAddrReg64:
1979 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1980 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1981 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1982 "expected immediate operand kind");
1983
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001984 return expandLoadAddress(Inst.getOperand(0).getReg(),
1985 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1986 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001987 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001988 ? MER_Fail
1989 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001990 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001991 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001992 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
1993 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001994 case Mips::SWM_MM:
1995 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001996 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
1997 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001998 case Mips::JalOneReg:
1999 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002000 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002001 case Mips::BneImm:
2002 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002003 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002004 case Mips::BLT:
2005 case Mips::BLE:
2006 case Mips::BGE:
2007 case Mips::BGT:
2008 case Mips::BLTU:
2009 case Mips::BLEU:
2010 case Mips::BGEU:
2011 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002012 case Mips::BLTL:
2013 case Mips::BLEL:
2014 case Mips::BGEL:
2015 case Mips::BGTL:
2016 case Mips::BLTUL:
2017 case Mips::BLEUL:
2018 case Mips::BGEUL:
2019 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002020 case Mips::BLTImmMacro:
2021 case Mips::BLEImmMacro:
2022 case Mips::BGEImmMacro:
2023 case Mips::BGTImmMacro:
2024 case Mips::BLTUImmMacro:
2025 case Mips::BLEUImmMacro:
2026 case Mips::BGEUImmMacro:
2027 case Mips::BGTUImmMacro:
2028 case Mips::BLTLImmMacro:
2029 case Mips::BLELImmMacro:
2030 case Mips::BGELImmMacro:
2031 case Mips::BGTLImmMacro:
2032 case Mips::BLTULImmMacro:
2033 case Mips::BLEULImmMacro:
2034 case Mips::BGEULImmMacro:
2035 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002036 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002037 case Mips::SDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002038 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2039 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002040 case Mips::DSDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002041 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2042 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002043 case Mips::UDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002044 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2045 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002046 case Mips::DUDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002047 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2048 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002049 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002050 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2051 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002052 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002053 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002054 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002055 case Mips::PseudoTRUNC_W_D:
2056 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2057 : MER_Success;
2058 case Mips::Ulh:
2059 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2060 case Mips::Ulhu:
2061 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2062 case Mips::Ulw:
2063 return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2064 case Mips::NORImm:
2065 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002066 case Mips::ADDi:
2067 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002068 case Mips::SLTi:
2069 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002070 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2071 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2072 int64_t ImmValue = Inst.getOperand(2).getImm();
2073 if (isInt<16>(ImmValue))
2074 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002075 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2076 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002077 }
2078 return MER_NotAMacro;
2079 case Mips::ANDi:
2080 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002081 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002082 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2083 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2084 int64_t ImmValue = Inst.getOperand(2).getImm();
2085 if (isUInt<16>(ImmValue))
2086 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002087 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2088 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002089 }
2090 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002091 case Mips::ROL:
2092 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002093 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002094 case Mips::ROLImm:
2095 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002096 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002097 case Mips::DROL:
2098 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002099 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002100 case Mips::DROLImm:
2101 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002102 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002103 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002104 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002105 }
Jack Carter30a59822012-10-04 04:03:53 +00002106}
Jack Carter92995f12012-10-06 00:53:28 +00002107
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002108bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002109 MCStreamer &Out,
2110 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002111 MipsTargetStreamer &TOut = getTargetStreamer();
2112
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002113 // Create a JALR instruction which is going to replace the pseudo-JAL.
2114 MCInst JalrInst;
2115 JalrInst.setLoc(IDLoc);
2116 const MCOperand FirstRegOp = Inst.getOperand(0);
2117 const unsigned Opcode = Inst.getOpcode();
2118
2119 if (Opcode == Mips::JalOneReg) {
2120 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002121 if (IsCpRestoreSet && inMicroMipsMode()) {
2122 JalrInst.setOpcode(Mips::JALRS16_MM);
2123 JalrInst.addOperand(FirstRegOp);
2124 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002125 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002126 JalrInst.addOperand(FirstRegOp);
2127 } else {
2128 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002129 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002130 JalrInst.addOperand(FirstRegOp);
2131 }
2132 } else if (Opcode == Mips::JalTwoReg) {
2133 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002134 if (IsCpRestoreSet && inMicroMipsMode())
2135 JalrInst.setOpcode(Mips::JALRS_MM);
2136 else
2137 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002138 JalrInst.addOperand(FirstRegOp);
2139 const MCOperand SecondRegOp = Inst.getOperand(1);
2140 JalrInst.addOperand(SecondRegOp);
2141 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002142 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002143
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002144 // If .set reorder is active and branch instruction has a delay slot,
2145 // emit a NOP after it.
2146 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002147 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2148 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2149 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002150
2151 return false;
2152}
2153
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002154/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002155template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002156 unsigned BitNum = findFirstSet(x);
2157
2158 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2159}
2160
2161/// Load (or add) an immediate into a register.
2162///
2163/// @param ImmValue The immediate to load.
2164/// @param DstReg The register that will hold the immediate.
2165/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2166/// for a simple initialization.
2167/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2168/// @param IsAddress True if the immediate represents an address. False if it
2169/// is an integer.
2170/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002171bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002172 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002173 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2174 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002175 MipsTargetStreamer &TOut = getTargetStreamer();
2176
Toma Tabacu00e98672015-05-01 12:19:27 +00002177 if (!Is32BitImm && !isGP64bit()) {
2178 Error(IDLoc, "instruction requires a 64-bit architecture");
2179 return true;
2180 }
2181
Daniel Sanders03f9c012015-07-14 12:24:22 +00002182 if (Is32BitImm) {
2183 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2184 // Sign extend up to 64-bit so that the predicates match the hardware
2185 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2186 // true.
2187 ImmValue = SignExtend64<32>(ImmValue);
2188 } else {
2189 Error(IDLoc, "instruction requires a 32-bit immediate");
2190 return true;
2191 }
2192 }
2193
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002194 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2195 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2196
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002197 bool UseSrcReg = false;
2198 if (SrcReg != Mips::NoRegister)
2199 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002200
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002201 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002202 if (UseSrcReg &&
2203 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002204 // At this point we need AT to perform the expansions and we exit if it is
2205 // not available.
2206 unsigned ATReg = getATReg(IDLoc);
2207 if (!ATReg)
2208 return true;
2209 TmpReg = ATReg;
2210 }
2211
Daniel Sanders03f9c012015-07-14 12:24:22 +00002212 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002213 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002214 SrcReg = ZeroReg;
2215
2216 // This doesn't quite follow the usual ABI expectations for N32 but matches
2217 // traditional assembler behaviour. N32 would normally use addiu for both
2218 // integers and addresses.
2219 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002220 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002221 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002222 }
2223
Daniel Sandersa736b372016-04-29 13:33:12 +00002224 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002225 return false;
2226 }
2227
2228 if (isUInt<16>(ImmValue)) {
2229 unsigned TmpReg = DstReg;
2230 if (SrcReg == DstReg) {
2231 TmpReg = getATReg(IDLoc);
2232 if (!TmpReg)
2233 return true;
2234 }
2235
Daniel Sandersa736b372016-04-29 13:33:12 +00002236 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002237 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002238 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002239 return false;
2240 }
2241
2242 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002243 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002244
Toma Tabacu79588102015-04-29 10:19:56 +00002245 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2246 uint16_t Bits15To0 = ImmValue & 0xffff;
2247
Toma Tabacua3d056f2015-05-15 09:42:11 +00002248 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002249 // Traditional behaviour seems to special case this particular value. It's
2250 // not clear why other masks are handled differently.
2251 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002252 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2253 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002254 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002255 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002256 return false;
2257 }
2258
2259 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002260 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002261 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2262 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002263 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002264 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002265 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002266 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002267 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002268 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002269
Daniel Sandersa736b372016-04-29 13:33:12 +00002270 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002271 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002272 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002273 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002274 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002275 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002276 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002277
2278 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2279 if (Is32BitImm) {
2280 Error(IDLoc, "instruction requires a 32-bit immediate");
2281 return true;
2282 }
2283
2284 // Traditionally, these immediates are shifted as little as possible and as
2285 // such we align the most significant bit to bit 15 of our temporary.
2286 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2287 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2288 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2289 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002290 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2291 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002292
2293 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002294 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002295
2296 return false;
2297 }
2298
2299 warnIfNoMacro(IDLoc);
2300
2301 // The remaining case is packed with a sequence of dsll and ori with zeros
2302 // being omitted and any neighbouring dsll's being coalesced.
2303 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2304
2305 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2306 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002307 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002308 return false;
2309
2310 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2311 // skip it and defer the shift to the next chunk.
2312 unsigned ShiftCarriedForwards = 16;
2313 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2314 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2315
2316 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002317 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2318 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002319 ShiftCarriedForwards = 0;
2320 }
2321
2322 ShiftCarriedForwards += 16;
2323 }
2324 ShiftCarriedForwards -= 16;
2325
2326 // Finish any remaining shifts left by trailing zeros.
2327 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002328 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002329
2330 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002331 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002332
Matheus Almeida3813d572014-06-19 14:39:14 +00002333 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002334}
Jack Carter92995f12012-10-06 00:53:28 +00002335
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002336bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002337 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002338 const MCOperand &ImmOp = Inst.getOperand(1);
2339 assert(ImmOp.isImm() && "expected immediate operand kind");
2340 const MCOperand &DstRegOp = Inst.getOperand(0);
2341 assert(DstRegOp.isReg() && "expected register operand kind");
2342
2343 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002344 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002345 return true;
2346
2347 return false;
2348}
2349
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002350bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2351 const MCOperand &Offset,
2352 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002353 MCStreamer &Out,
2354 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002355 // la can't produce a usable address when addresses are 64-bit.
2356 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2357 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2358 // We currently can't do this because we depend on the equality
2359 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2360 Error(IDLoc, "la used to load 64-bit address");
2361 // Continue as if we had 'dla' instead.
2362 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002363 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002364
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002365 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002366 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002367 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002368 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002369 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002370
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002371 if (!Offset.isImm())
2372 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002373 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002374
Scott Egerton24557012016-01-21 15:11:01 +00002375 if (!ABI.ArePtrs64bit()) {
2376 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2377 Is32BitAddress = true;
2378 }
2379
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002380 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002381 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002382}
2383
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002384bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2385 unsigned DstReg, unsigned SrcReg,
2386 bool Is32BitSym, SMLoc IDLoc,
2387 MCStreamer &Out,
2388 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002389 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002390 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002391 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002392
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002393 if (inPicMode() && ABI.IsO32()) {
2394 MCValue Res;
2395 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2396 Error(IDLoc, "expected relocatable expression");
2397 return true;
2398 }
2399 if (Res.getSymB() != nullptr) {
2400 Error(IDLoc, "expected relocatable expression with only one symbol");
2401 return true;
2402 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002403
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002404 // The case where the result register is $25 is somewhat special. If the
2405 // symbol in the final relocation is external and not modified with a
2406 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2407 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2408 Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
2409 !Res.getSymA()->getSymbol().isTemporary()) {
2410 const MCExpr *CallExpr =
2411 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2412 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2413 MCOperand::createExpr(CallExpr), IDLoc, STI);
2414 return false;
2415 }
2416
2417 // The remaining cases are:
2418 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2419 // >addiu $tmp, $tmp, %lo(offset)
2420 // >addiu $rd, $tmp, $rs
2421 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2422 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2423 // >addiu $rd, $tmp, $rs
2424 // The addiu's marked with a '>' may be omitted if they are redundant. If
2425 // this happens then the last instruction must use $rd as the result
2426 // register.
2427 const MipsMCExpr *GotExpr =
2428 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2429 const MCExpr *LoExpr = nullptr;
2430 if (Res.getSymA()->getSymbol().isInSection() ||
2431 Res.getSymA()->getSymbol().isTemporary())
2432 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2433 else if (Res.getConstant() != 0) {
2434 // External symbols fully resolve the symbol with just the %got(symbol)
2435 // but we must still account for any offset to the symbol for expressions
2436 // like symbol+8.
2437 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2438 }
2439
2440 unsigned TmpReg = DstReg;
2441 if (UseSrcReg &&
2442 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2443 SrcReg)) {
2444 // If $rs is the same as $rd, we need to use AT.
2445 // If it is not available we exit.
2446 unsigned ATReg = getATReg(IDLoc);
2447 if (!ATReg)
2448 return true;
2449 TmpReg = ATReg;
2450 }
2451
2452 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2453 MCOperand::createExpr(GotExpr), IDLoc, STI);
2454
2455 if (LoExpr)
2456 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2457 IDLoc, STI);
2458
2459 if (UseSrcReg)
2460 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2461
2462 return false;
2463 }
2464
2465 const MipsMCExpr *HiExpr =
2466 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2467 const MipsMCExpr *LoExpr =
2468 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002469
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002470 // This is the 64-bit symbol address expansion.
2471 if (ABI.ArePtrs64bit() && isGP64bit()) {
2472 // We always need AT for the 64-bit expansion.
2473 // If it is not available we exit.
2474 unsigned ATReg = getATReg(IDLoc);
2475 if (!ATReg)
2476 return true;
2477
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002478 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002479 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002480 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002481 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002482
Scott Egerton24557012016-01-21 15:11:01 +00002483 if (UseSrcReg &&
2484 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2485 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002486 // If $rs is the same as $rd:
2487 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2488 // daddiu $at, $at, %higher(sym)
2489 // dsll $at, $at, 16
2490 // daddiu $at, $at, %hi(sym)
2491 // dsll $at, $at, 16
2492 // daddiu $at, $at, %lo(sym)
2493 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002494 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2495 STI);
2496 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2497 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2498 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2499 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2500 IDLoc, STI);
2501 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2502 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2503 IDLoc, STI);
2504 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002505
2506 return false;
2507 }
2508
2509 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2510 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2511 // lui $at, %hi(sym)
2512 // daddiu $rd, $rd, %higher(sym)
2513 // daddiu $at, $at, %lo(sym)
2514 // dsll32 $rd, $rd, 0
2515 // daddu $rd, $rd, $at
2516 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002517 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2518 STI);
2519 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2520 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2521 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2522 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2523 IDLoc, STI);
2524 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2525 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002526 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002527 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002528
2529 return false;
2530 }
2531
2532 // And now, the 32-bit symbol address expansion:
2533 // If $rs is the same as $rd:
2534 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2535 // ori $at, $at, %lo(sym)
2536 // addu $rd, $at, $rd
2537 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2538 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2539 // ori $rd, $rd, %lo(sym)
2540 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002541 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002542 if (UseSrcReg &&
2543 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002544 // If $rs is the same as $rd, we need to use AT.
2545 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002546 unsigned ATReg = getATReg(IDLoc);
2547 if (!ATReg)
2548 return true;
2549 TmpReg = ATReg;
2550 }
2551
Daniel Sandersa736b372016-04-29 13:33:12 +00002552 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2553 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2554 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002555
Toma Tabacufb9d1252015-06-22 12:08:39 +00002556 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002557 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002558 else
Scott Egerton24557012016-01-21 15:11:01 +00002559 assert(
2560 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002561
Toma Tabacu674825c2015-06-16 12:16:24 +00002562 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002563}
2564
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002565bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2566 MCStreamer &Out,
2567 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002568 MipsTargetStreamer &TOut = getTargetStreamer();
2569
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002570 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2571 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002572
2573 MCOperand Offset = Inst.getOperand(0);
2574 if (Offset.isExpr()) {
2575 Inst.clear();
2576 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002577 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2578 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2579 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002580 } else {
2581 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002582 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002583 // If offset fits into 11 bits then this instruction becomes microMIPS
2584 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002585 if (inMicroMipsMode())
2586 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002587 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002588 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002589 Error(IDLoc, "branch target out of range");
2590 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2591 Error(IDLoc, "branch to misaligned address");
2592 Inst.clear();
2593 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002594 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2595 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2596 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002597 }
2598 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002599 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002600
Zoran Jovanovicada70912015-09-07 11:56:37 +00002601 // If .set reorder is active and branch instruction has a delay slot,
2602 // emit a NOP after it.
2603 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2604 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002605 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002606
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002607 return false;
2608}
2609
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002610bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2611 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002612 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002613 const MCOperand &DstRegOp = Inst.getOperand(0);
2614 assert(DstRegOp.isReg() && "expected register operand kind");
2615
2616 const MCOperand &ImmOp = Inst.getOperand(1);
2617 assert(ImmOp.isImm() && "expected immediate operand kind");
2618
2619 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002620 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2621 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002622
2623 unsigned OpCode = 0;
2624 switch(Inst.getOpcode()) {
2625 case Mips::BneImm:
2626 OpCode = Mips::BNE;
2627 break;
2628 case Mips::BeqImm:
2629 OpCode = Mips::BEQ;
2630 break;
2631 default:
2632 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2633 break;
2634 }
2635
2636 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002637 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002638 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2639 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002640 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002641 warnIfNoMacro(IDLoc);
2642
2643 unsigned ATReg = getATReg(IDLoc);
2644 if (!ATReg)
2645 return true;
2646
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002647 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002648 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002649 return true;
2650
Daniel Sandersa736b372016-04-29 13:33:12 +00002651 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002652 }
2653 return false;
2654}
2655
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002656void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002657 const MCSubtargetInfo *STI, bool IsLoad,
2658 bool IsImmOpnd) {
2659 if (IsLoad) {
2660 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2661 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002662 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002663 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2664}
2665
2666void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2667 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2668 MipsTargetStreamer &TOut = getTargetStreamer();
2669
2670 unsigned DstReg = Inst.getOperand(0).getReg();
2671 unsigned BaseReg = Inst.getOperand(1).getReg();
2672
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002673 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002674 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2675 unsigned DstRegClassID =
2676 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2677 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2678 (DstRegClassID == Mips::GPR64RegClassID);
2679
2680 if (IsImmOpnd) {
2681 // Try to use DstReg as the temporary.
2682 if (IsGPR && (BaseReg != DstReg)) {
2683 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2684 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2685 STI);
2686 return;
2687 }
2688
Matheus Almeida7de68e72014-06-18 14:46:05 +00002689 // At this point we need AT to perform the expansions and we exit if it is
2690 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002691 unsigned ATReg = getATReg(IDLoc);
2692 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002693 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002694
2695 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2696 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2697 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002698 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002699
Daniel Sandersfba875f2016-04-29 13:43:45 +00002700 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002701 MCOperand LoOperand = MCOperand::createExpr(
2702 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2703 MCOperand HiOperand = MCOperand::createExpr(
2704 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002705
2706 // Try to use DstReg as the temporary.
2707 if (IsGPR && (BaseReg != DstReg)) {
2708 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2709 LoOperand, DstReg, IDLoc, STI);
2710 return;
2711 }
2712
2713 // At this point we need AT to perform the expansions and we exit if it is
2714 // not available.
2715 unsigned ATReg = getATReg(IDLoc);
2716 if (!ATReg)
2717 return;
2718
2719 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2720 LoOperand, ATReg, IDLoc, STI);
2721}
2722
2723void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2724 const MCSubtargetInfo *STI,
2725 bool IsImmOpnd) {
2726 MipsTargetStreamer &TOut = getTargetStreamer();
2727
2728 unsigned SrcReg = Inst.getOperand(0).getReg();
2729 unsigned BaseReg = Inst.getOperand(1).getReg();
2730
Daniel Sanders241c6792016-05-12 14:01:50 +00002731 if (IsImmOpnd) {
2732 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2733 Inst.getOperand(2).getImm(),
2734 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
2735 return;
2736 }
2737
Daniel Sandersfba875f2016-04-29 13:43:45 +00002738 unsigned ATReg = getATReg(IDLoc);
2739 if (!ATReg)
2740 return;
2741
Daniel Sandersfba875f2016-04-29 13:43:45 +00002742 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002743 MCOperand LoOperand = MCOperand::createExpr(
2744 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2745 MCOperand HiOperand = MCOperand::createExpr(
2746 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002747 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2748 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002749}
2750
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002751bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2752 MCStreamer &Out,
2753 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002754 unsigned OpNum = Inst.getNumOperands();
2755 unsigned Opcode = Inst.getOpcode();
2756 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2757
2758 assert (Inst.getOperand(OpNum - 1).isImm() &&
2759 Inst.getOperand(OpNum - 2).isReg() &&
2760 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2761
2762 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2763 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002764 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2765 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2766 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2767 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002768 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002769 if (inMicroMipsMode() && hasMips32r6())
2770 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2771 else
2772 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2773 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002774
2775 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002776 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002777 return false;
2778}
2779
Toma Tabacu1a108322015-06-17 13:20:24 +00002780bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002781 MCStreamer &Out,
2782 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002783 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002784 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002785 unsigned PseudoOpcode = Inst.getOpcode();
2786 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002787 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002788 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2789
2790 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002791 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002792
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002793 unsigned TrgReg;
2794 if (TrgOp.isReg())
2795 TrgReg = TrgOp.getReg();
2796 else if (TrgOp.isImm()) {
2797 warnIfNoMacro(IDLoc);
2798 EmittedNoMacroWarning = true;
2799
2800 TrgReg = getATReg(IDLoc);
2801 if (!TrgReg)
2802 return true;
2803
2804 switch(PseudoOpcode) {
2805 default:
2806 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2807 case Mips::BLTImmMacro:
2808 PseudoOpcode = Mips::BLT;
2809 break;
2810 case Mips::BLEImmMacro:
2811 PseudoOpcode = Mips::BLE;
2812 break;
2813 case Mips::BGEImmMacro:
2814 PseudoOpcode = Mips::BGE;
2815 break;
2816 case Mips::BGTImmMacro:
2817 PseudoOpcode = Mips::BGT;
2818 break;
2819 case Mips::BLTUImmMacro:
2820 PseudoOpcode = Mips::BLTU;
2821 break;
2822 case Mips::BLEUImmMacro:
2823 PseudoOpcode = Mips::BLEU;
2824 break;
2825 case Mips::BGEUImmMacro:
2826 PseudoOpcode = Mips::BGEU;
2827 break;
2828 case Mips::BGTUImmMacro:
2829 PseudoOpcode = Mips::BGTU;
2830 break;
2831 case Mips::BLTLImmMacro:
2832 PseudoOpcode = Mips::BLTL;
2833 break;
2834 case Mips::BLELImmMacro:
2835 PseudoOpcode = Mips::BLEL;
2836 break;
2837 case Mips::BGELImmMacro:
2838 PseudoOpcode = Mips::BGEL;
2839 break;
2840 case Mips::BGTLImmMacro:
2841 PseudoOpcode = Mips::BGTL;
2842 break;
2843 case Mips::BLTULImmMacro:
2844 PseudoOpcode = Mips::BLTUL;
2845 break;
2846 case Mips::BLEULImmMacro:
2847 PseudoOpcode = Mips::BLEUL;
2848 break;
2849 case Mips::BGEULImmMacro:
2850 PseudoOpcode = Mips::BGEUL;
2851 break;
2852 case Mips::BGTULImmMacro:
2853 PseudoOpcode = Mips::BGTUL;
2854 break;
2855 }
2856
2857 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002858 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002859 return true;
2860 }
2861
Toma Tabacu1a108322015-06-17 13:20:24 +00002862 switch (PseudoOpcode) {
2863 case Mips::BLT:
2864 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002865 case Mips::BLTL:
2866 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002867 AcceptsEquality = false;
2868 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002869 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2870 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002871 ZeroSrcOpcode = Mips::BGTZ;
2872 ZeroTrgOpcode = Mips::BLTZ;
2873 break;
2874 case Mips::BLE:
2875 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002876 case Mips::BLEL:
2877 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002878 AcceptsEquality = true;
2879 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002880 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2881 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002882 ZeroSrcOpcode = Mips::BGEZ;
2883 ZeroTrgOpcode = Mips::BLEZ;
2884 break;
2885 case Mips::BGE:
2886 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002887 case Mips::BGEL:
2888 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002889 AcceptsEquality = true;
2890 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002891 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2892 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002893 ZeroSrcOpcode = Mips::BLEZ;
2894 ZeroTrgOpcode = Mips::BGEZ;
2895 break;
2896 case Mips::BGT:
2897 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002898 case Mips::BGTL:
2899 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002900 AcceptsEquality = false;
2901 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002902 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2903 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002904 ZeroSrcOpcode = Mips::BLTZ;
2905 ZeroTrgOpcode = Mips::BGTZ;
2906 break;
2907 default:
2908 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2909 }
2910
Toma Tabacu1a108322015-06-17 13:20:24 +00002911 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2912 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2913 if (IsSrcRegZero && IsTrgRegZero) {
2914 // FIXME: All of these Opcode-specific if's are needed for compatibility
2915 // with GAS' behaviour. However, they may not generate the most efficient
2916 // code in some circumstances.
2917 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002918 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2919 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002920 return false;
2921 }
2922 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002923 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2924 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002925 Warning(IDLoc, "branch is always taken");
2926 return false;
2927 }
2928 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002929 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2930 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002931 Warning(IDLoc, "branch is always taken");
2932 return false;
2933 }
2934 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002935 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2936 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002937 return false;
2938 }
2939 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002940 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2941 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002942 return false;
2943 }
2944 if (AcceptsEquality) {
2945 // If both registers are $0 and the pseudo-branch accepts equality, it
2946 // will always be taken, so we emit an unconditional branch.
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 both registers are $0 and the pseudo-branch does not accept
2953 // equality, it will never be taken, so we don't have to emit anything.
2954 return false;
2955 }
2956 if (IsSrcRegZero || IsTrgRegZero) {
2957 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2958 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2959 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2960 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2961 // the pseudo-branch will never be taken, so we don't emit anything.
2962 // This only applies to unsigned pseudo-branches.
2963 return false;
2964 }
2965 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2966 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2967 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2968 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2969 // the pseudo-branch will always be taken, so we emit an unconditional
2970 // branch.
2971 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00002972 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2973 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002974 Warning(IDLoc, "branch is always taken");
2975 return false;
2976 }
2977 if (IsUnsigned) {
2978 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2979 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2980 // the pseudo-branch will be taken only when the non-zero register is
2981 // different from 0, so we emit a BNEZ.
2982 //
2983 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2984 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2985 // the pseudo-branch will be taken only when the non-zero register is
2986 // equal to 0, so we emit a BEQZ.
2987 //
2988 // Because only BLEU and BGEU branch on equality, we can use the
2989 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00002990 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2991 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2992 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002993 return false;
2994 }
2995 // If we have a signed pseudo-branch and one of the registers is $0,
2996 // we can use an appropriate compare-to-zero branch. We select which one
2997 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00002998 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2999 IsSrcRegZero ? TrgReg : SrcReg,
3000 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003001 return false;
3002 }
3003
3004 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3005 // expansions. If it is not available, we return.
3006 unsigned ATRegNum = getATReg(IDLoc);
3007 if (!ATRegNum)
3008 return true;
3009
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003010 if (!EmittedNoMacroWarning)
3011 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003012
3013 // SLT fits well with 2 of our 4 pseudo-branches:
3014 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3015 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3016 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3017 // This is accomplished by using a BNEZ with the result of the SLT.
3018 //
3019 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3020 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3021 // Because only BGE and BLE branch on equality, we can use the
3022 // AcceptsEquality variable to decide when to emit the BEQZ.
3023 // Note that the order of the SLT arguments doesn't change between
3024 // opposites.
3025 //
3026 // The same applies to the unsigned variants, except that SLTu is used
3027 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003028 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3029 ReverseOrderSLT ? TrgReg : SrcReg,
3030 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003031
Daniel Sandersa736b372016-04-29 13:33:12 +00003032 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3033 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3034 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3035 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003036 return false;
3037}
3038
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003039bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3040 const MCSubtargetInfo *STI, const bool IsMips64,
3041 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003042 MipsTargetStreamer &TOut = getTargetStreamer();
3043
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003044 warnIfNoMacro(IDLoc);
3045
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003046 const MCOperand &RdRegOp = Inst.getOperand(0);
3047 assert(RdRegOp.isReg() && "expected register operand kind");
3048 unsigned RdReg = RdRegOp.getReg();
3049
3050 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003051 assert(RsRegOp.isReg() && "expected register operand kind");
3052 unsigned RsReg = RsRegOp.getReg();
3053
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003054 const MCOperand &RtRegOp = Inst.getOperand(2);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003055 assert(RtRegOp.isReg() && "expected register operand kind");
3056 unsigned RtReg = RtRegOp.getReg();
3057 unsigned DivOp;
3058 unsigned ZeroReg;
3059
3060 if (IsMips64) {
3061 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3062 ZeroReg = Mips::ZERO_64;
3063 } else {
3064 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3065 ZeroReg = Mips::ZERO;
3066 }
3067
3068 bool UseTraps = useTraps();
3069
3070 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
3071 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
3072 Warning(IDLoc, "dividing zero by zero");
3073 if (IsMips64) {
3074 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
3075 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003076 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003077 return false;
3078 }
3079
Daniel Sandersa736b372016-04-29 13:33:12 +00003080 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003081 return false;
3082 }
3083 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00003084 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003085 return false;
3086 }
3087 }
3088
3089 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3090 Warning(IDLoc, "division by zero");
3091 if (Signed) {
3092 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003093 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003094 return false;
3095 }
3096
Daniel Sandersa736b372016-04-29 13:33:12 +00003097 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003098 return false;
3099 }
3100 }
3101
3102 // FIXME: The values for these two BranchTarget variables may be different in
3103 // micromips. These magic numbers need to be removed.
3104 unsigned BranchTargetNoTraps;
3105 unsigned BranchTarget;
3106
3107 if (UseTraps) {
3108 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003109 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003110 } else {
3111 BranchTarget = IsMips64 ? 20 : 16;
3112 BranchTargetNoTraps = 8;
3113 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003114 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003115 }
3116
Daniel Sandersa736b372016-04-29 13:33:12 +00003117 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003118
3119 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003120 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003121
3122 if (!Signed) {
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003123 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003124 return false;
3125 }
3126
3127 unsigned ATReg = getATReg(IDLoc);
3128 if (!ATReg)
3129 return true;
3130
Daniel Sandersa736b372016-04-29 13:33:12 +00003131 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003132 if (IsMips64) {
3133 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003134 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3135 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3136 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003137 } else {
3138 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003139 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3140 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003141 }
3142
3143 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003144 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003145 else {
3146 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003147 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3148 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3149 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003150 }
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003151 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003152 return false;
3153}
3154
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003155bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003156 SMLoc IDLoc, MCStreamer &Out,
3157 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003158 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003159
3160 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3161 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3162 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3163
3164 unsigned FirstReg = Inst.getOperand(0).getReg();
3165 unsigned SecondReg = Inst.getOperand(1).getReg();
3166 unsigned ThirdReg = Inst.getOperand(2).getReg();
3167
3168 if (hasMips1() && !hasMips2()) {
3169 unsigned ATReg = getATReg(IDLoc);
3170 if (!ATReg)
3171 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003172 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3173 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3174 TOut.emitNop(IDLoc, STI);
3175 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3176 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3177 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3178 TOut.emitNop(IDLoc, STI);
3179 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3180 : Mips::CVT_W_S,
3181 FirstReg, SecondReg, IDLoc, STI);
3182 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3183 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003184 return false;
3185 }
3186
Daniel Sandersa736b372016-04-29 13:33:12 +00003187 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3188 : Mips::TRUNC_W_S,
3189 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003190
3191 return false;
3192}
3193
Daniel Sanders6394ee52015-10-15 14:52:58 +00003194bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003195 MCStreamer &Out, const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003196 MipsTargetStreamer &TOut = getTargetStreamer();
3197
Toma Tabacud88d79c2015-06-23 14:39:42 +00003198 if (hasMips32r6() || hasMips64r6()) {
3199 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3200 return false;
3201 }
3202
3203 warnIfNoMacro(IDLoc);
3204
3205 const MCOperand &DstRegOp = Inst.getOperand(0);
3206 assert(DstRegOp.isReg() && "expected register operand kind");
3207
3208 const MCOperand &SrcRegOp = Inst.getOperand(1);
3209 assert(SrcRegOp.isReg() && "expected register operand kind");
3210
3211 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3212 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3213
3214 unsigned DstReg = DstRegOp.getReg();
3215 unsigned SrcReg = SrcRegOp.getReg();
3216 int64_t OffsetValue = OffsetImmOp.getImm();
3217
3218 // NOTE: We always need AT for ULHU, as it is always used as the source
3219 // register for one of the LBu's.
3220 unsigned ATReg = getATReg(IDLoc);
3221 if (!ATReg)
3222 return true;
3223
3224 // When the value of offset+1 does not fit in 16 bits, we have to load the
3225 // offset in AT, (D)ADDu the original source register (if there was one), and
3226 // then use AT as the source register for the 2 generated LBu's.
3227 bool LoadedOffsetInAT = false;
3228 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3229 LoadedOffsetInAT = true;
3230
3231 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003232 true, IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003233 return true;
3234
3235 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3236 // because it will make our output more similar to GAS'. For example,
3237 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3238 // instead of just an "ori $1, $9, 32768".
3239 // NOTE: If there is no source register specified in the ULHU, the parser
3240 // will interpret it as $0.
3241 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003242 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003243 }
3244
3245 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3246 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3247 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3248
3249 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3250 if (isLittle()) {
3251 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3252 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3253 } else {
3254 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3255 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3256 }
3257
3258 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3259
Daniel Sandersa736b372016-04-29 13:33:12 +00003260 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3261 FirstLbuOffset, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003262
Daniel Sandersa736b372016-04-29 13:33:12 +00003263 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3264 STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003265
Daniel Sandersa736b372016-04-29 13:33:12 +00003266 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003267
Daniel Sandersa736b372016-04-29 13:33:12 +00003268 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003269
3270 return false;
3271}
3272
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003273bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3274 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003275 MipsTargetStreamer &TOut = getTargetStreamer();
3276
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003277 if (hasMips32r6() || hasMips64r6()) {
3278 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3279 return false;
3280 }
3281
3282 const MCOperand &DstRegOp = Inst.getOperand(0);
3283 assert(DstRegOp.isReg() && "expected register operand kind");
3284
3285 const MCOperand &SrcRegOp = Inst.getOperand(1);
3286 assert(SrcRegOp.isReg() && "expected register operand kind");
3287
3288 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3289 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3290
3291 unsigned SrcReg = SrcRegOp.getReg();
3292 int64_t OffsetValue = OffsetImmOp.getImm();
3293 unsigned ATReg = 0;
3294
3295 // When the value of offset+3 does not fit in 16 bits, we have to load the
3296 // offset in AT, (D)ADDu the original source register (if there was one), and
3297 // then use AT as the source register for the generated LWL and LWR.
3298 bool LoadedOffsetInAT = false;
3299 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3300 ATReg = getATReg(IDLoc);
3301 if (!ATReg)
3302 return true;
3303 LoadedOffsetInAT = true;
3304
3305 warnIfNoMacro(IDLoc);
3306
3307 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003308 true, IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003309 return true;
3310
3311 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3312 // because it will make our output more similar to GAS'. For example,
3313 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3314 // instead of just an "ori $1, $9, 32768".
3315 // NOTE: If there is no source register specified in the ULW, the parser
3316 // will interpret it as $0.
3317 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003318 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003319 }
3320
3321 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3322 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3323 if (isLittle()) {
3324 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3325 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3326 } else {
3327 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3328 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3329 }
3330
Daniel Sandersa736b372016-04-29 13:33:12 +00003331 TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3332 STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003333
Daniel Sandersa736b372016-04-29 13:33:12 +00003334 TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
3335 IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003336
3337 return false;
3338}
3339
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003340bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003341 MCStreamer &Out,
3342 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003343 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003344
3345 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3346 assert (Inst.getOperand(0).isReg() &&
3347 Inst.getOperand(1).isReg() &&
3348 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3349
3350 unsigned ATReg = Mips::NoRegister;
3351 unsigned FinalDstReg = Mips::NoRegister;
3352 unsigned DstReg = Inst.getOperand(0).getReg();
3353 unsigned SrcReg = Inst.getOperand(1).getReg();
3354 int64_t ImmValue = Inst.getOperand(2).getImm();
3355
3356 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3357
3358 unsigned FinalOpcode = Inst.getOpcode();
3359
3360 if (DstReg == SrcReg) {
3361 ATReg = getATReg(Inst.getLoc());
3362 if (!ATReg)
3363 return true;
3364 FinalDstReg = DstReg;
3365 DstReg = ATReg;
3366 }
3367
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003368 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003369 switch (FinalOpcode) {
3370 default:
3371 llvm_unreachable("unimplemented expansion");
3372 case (Mips::ADDi):
3373 FinalOpcode = Mips::ADD;
3374 break;
3375 case (Mips::ADDiu):
3376 FinalOpcode = Mips::ADDu;
3377 break;
3378 case (Mips::ANDi):
3379 FinalOpcode = Mips::AND;
3380 break;
3381 case (Mips::NORImm):
3382 FinalOpcode = Mips::NOR;
3383 break;
3384 case (Mips::ORi):
3385 FinalOpcode = Mips::OR;
3386 break;
3387 case (Mips::SLTi):
3388 FinalOpcode = Mips::SLT;
3389 break;
3390 case (Mips::SLTiu):
3391 FinalOpcode = Mips::SLTu;
3392 break;
3393 case (Mips::XORi):
3394 FinalOpcode = Mips::XOR;
3395 break;
3396 }
3397
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003398 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003399 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003400 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003401 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003402 return false;
3403 }
3404 return true;
3405}
3406
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003407bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3408 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003409 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003410 unsigned ATReg = Mips::NoRegister;
3411 unsigned DReg = Inst.getOperand(0).getReg();
3412 unsigned SReg = Inst.getOperand(1).getReg();
3413 unsigned TReg = Inst.getOperand(2).getReg();
3414 unsigned TmpReg = DReg;
3415
3416 unsigned FirstShift = Mips::NOP;
3417 unsigned SecondShift = Mips::NOP;
3418
3419 if (hasMips32r2()) {
3420
3421 if (DReg == SReg) {
3422 TmpReg = getATReg(Inst.getLoc());
3423 if (!TmpReg)
3424 return true;
3425 }
3426
3427 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003428 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3429 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003430 return false;
3431 }
3432
3433 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003434 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003435 return false;
3436 }
3437
3438 return true;
3439 }
3440
3441 if (hasMips32()) {
3442
3443 switch (Inst.getOpcode()) {
3444 default:
3445 llvm_unreachable("unexpected instruction opcode");
3446 case Mips::ROL:
3447 FirstShift = Mips::SRLV;
3448 SecondShift = Mips::SLLV;
3449 break;
3450 case Mips::ROR:
3451 FirstShift = Mips::SLLV;
3452 SecondShift = Mips::SRLV;
3453 break;
3454 }
3455
3456 ATReg = getATReg(Inst.getLoc());
3457 if (!ATReg)
3458 return true;
3459
Daniel Sandersa736b372016-04-29 13:33:12 +00003460 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3461 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3462 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3463 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003464
3465 return false;
3466 }
3467
3468 return true;
3469}
3470
3471bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003472 MCStreamer &Out,
3473 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003474 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003475 unsigned ATReg = Mips::NoRegister;
3476 unsigned DReg = Inst.getOperand(0).getReg();
3477 unsigned SReg = Inst.getOperand(1).getReg();
3478 int64_t ImmValue = Inst.getOperand(2).getImm();
3479
3480 unsigned FirstShift = Mips::NOP;
3481 unsigned SecondShift = Mips::NOP;
3482
3483 if (hasMips32r2()) {
3484
3485 if (Inst.getOpcode() == Mips::ROLImm) {
3486 uint64_t MaxShift = 32;
3487 uint64_t ShiftValue = ImmValue;
3488 if (ImmValue != 0)
3489 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003490 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003491 return false;
3492 }
3493
3494 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003495 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003496 return false;
3497 }
3498
3499 return true;
3500 }
3501
3502 if (hasMips32()) {
3503
3504 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003505 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003506 return false;
3507 }
3508
3509 switch (Inst.getOpcode()) {
3510 default:
3511 llvm_unreachable("unexpected instruction opcode");
3512 case Mips::ROLImm:
3513 FirstShift = Mips::SLL;
3514 SecondShift = Mips::SRL;
3515 break;
3516 case Mips::RORImm:
3517 FirstShift = Mips::SRL;
3518 SecondShift = Mips::SLL;
3519 break;
3520 }
3521
3522 ATReg = getATReg(Inst.getLoc());
3523 if (!ATReg)
3524 return true;
3525
Daniel Sandersa736b372016-04-29 13:33:12 +00003526 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3527 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3528 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003529
3530 return false;
3531 }
3532
3533 return true;
3534}
3535
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003536bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3537 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003538 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003539 unsigned ATReg = Mips::NoRegister;
3540 unsigned DReg = Inst.getOperand(0).getReg();
3541 unsigned SReg = Inst.getOperand(1).getReg();
3542 unsigned TReg = Inst.getOperand(2).getReg();
3543 unsigned TmpReg = DReg;
3544
3545 unsigned FirstShift = Mips::NOP;
3546 unsigned SecondShift = Mips::NOP;
3547
3548 if (hasMips64r2()) {
3549
3550 if (TmpReg == SReg) {
3551 TmpReg = getATReg(Inst.getLoc());
3552 if (!TmpReg)
3553 return true;
3554 }
3555
3556 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003557 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3558 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003559 return false;
3560 }
3561
3562 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003563 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003564 return false;
3565 }
3566
3567 return true;
3568 }
3569
3570 if (hasMips64()) {
3571
3572 switch (Inst.getOpcode()) {
3573 default:
3574 llvm_unreachable("unexpected instruction opcode");
3575 case Mips::DROL:
3576 FirstShift = Mips::DSRLV;
3577 SecondShift = Mips::DSLLV;
3578 break;
3579 case Mips::DROR:
3580 FirstShift = Mips::DSLLV;
3581 SecondShift = Mips::DSRLV;
3582 break;
3583 }
3584
3585 ATReg = getATReg(Inst.getLoc());
3586 if (!ATReg)
3587 return true;
3588
Daniel Sandersa736b372016-04-29 13:33:12 +00003589 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3590 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3591 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3592 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003593
3594 return false;
3595 }
3596
3597 return true;
3598}
3599
3600bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003601 MCStreamer &Out,
3602 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003603 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003604 unsigned ATReg = Mips::NoRegister;
3605 unsigned DReg = Inst.getOperand(0).getReg();
3606 unsigned SReg = Inst.getOperand(1).getReg();
3607 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3608
3609 unsigned FirstShift = Mips::NOP;
3610 unsigned SecondShift = Mips::NOP;
3611
3612 MCInst TmpInst;
3613
3614 if (hasMips64r2()) {
3615
3616 unsigned FinalOpcode = Mips::NOP;
3617 if (ImmValue == 0)
3618 FinalOpcode = Mips::DROTR;
3619 else if (ImmValue % 32 == 0)
3620 FinalOpcode = Mips::DROTR32;
3621 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3622 if (Inst.getOpcode() == Mips::DROLImm)
3623 FinalOpcode = Mips::DROTR32;
3624 else
3625 FinalOpcode = Mips::DROTR;
3626 } else if (ImmValue >= 33) {
3627 if (Inst.getOpcode() == Mips::DROLImm)
3628 FinalOpcode = Mips::DROTR;
3629 else
3630 FinalOpcode = Mips::DROTR32;
3631 }
3632
3633 uint64_t ShiftValue = ImmValue % 32;
3634 if (Inst.getOpcode() == Mips::DROLImm)
3635 ShiftValue = (32 - ImmValue % 32) % 32;
3636
Daniel Sandersa736b372016-04-29 13:33:12 +00003637 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003638
3639 return false;
3640 }
3641
3642 if (hasMips64()) {
3643
3644 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003645 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003646 return false;
3647 }
3648
3649 switch (Inst.getOpcode()) {
3650 default:
3651 llvm_unreachable("unexpected instruction opcode");
3652 case Mips::DROLImm:
3653 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3654 FirstShift = Mips::DSLL;
3655 SecondShift = Mips::DSRL32;
3656 }
3657 if (ImmValue == 32) {
3658 FirstShift = Mips::DSLL32;
3659 SecondShift = Mips::DSRL32;
3660 }
3661 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3662 FirstShift = Mips::DSLL32;
3663 SecondShift = Mips::DSRL;
3664 }
3665 break;
3666 case Mips::DRORImm:
3667 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3668 FirstShift = Mips::DSRL;
3669 SecondShift = Mips::DSLL32;
3670 }
3671 if (ImmValue == 32) {
3672 FirstShift = Mips::DSRL32;
3673 SecondShift = Mips::DSLL32;
3674 }
3675 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3676 FirstShift = Mips::DSRL32;
3677 SecondShift = Mips::DSLL;
3678 }
3679 break;
3680 }
3681
3682 ATReg = getATReg(Inst.getLoc());
3683 if (!ATReg)
3684 return true;
3685
Daniel Sandersa736b372016-04-29 13:33:12 +00003686 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3687 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3688 Inst.getLoc(), STI);
3689 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003690
3691 return false;
3692 }
3693
3694 return true;
3695}
3696
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003697bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3698 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003699 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003700 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3701 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3702
Daniel Sandersa736b372016-04-29 13:33:12 +00003703 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003704 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003705 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003706 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003707 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3708 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003709
3710 return false;
3711}
3712
Daniel Sandersc5537422016-07-27 13:49:44 +00003713unsigned
3714MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
3715 const OperandVector &Operands) {
3716 switch (Inst.getOpcode()) {
3717 default:
3718 return Match_Success;
3719 case Mips::DATI:
3720 case Mips::DAHI:
Daniel Sandersb23005e2016-07-28 15:59:06 +00003721 if (static_cast<MipsOperand &>(*Operands[1])
3722 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
3723 return Match_Success;
3724 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00003725 }
3726}
Matheus Almeida595fcab2014-06-11 15:05:56 +00003727unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00003728 switch (Inst.getOpcode()) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003729 // As described by the Mips32r2 spec, the registers Rd and Rs for
3730 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00003731 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00003732 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00003733 case Mips::JALR_HB:
3734 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00003735 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00003736 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
3737 return Match_RequiresDifferentSrcAndDst;
3738 return Match_Success;
3739 case Mips::LWP_MM:
3740 case Mips::LWP_MMR6:
3741 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
3742 return Match_RequiresDifferentSrcAndDst;
3743 return Match_Success;
3744 // As described the MIPSR6 spec, the compact branches that compare registers
3745 // must:
3746 // a) Not use the zero register.
3747 // b) Not use the same register twice.
3748 // c) rs < rt for bnec, beqc.
3749 // NB: For this case, the encoding will swap the operands as their
3750 // ordering doesn't matter. GAS performs this transformation too.
3751 // Hence, that constraint does not have to be enforced.
3752 //
3753 // The compact branches that branch iff the signed addition of two registers
3754 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
3755 // operand swapping. They do not have restriction of using the zero register.
3756 case Mips::BLEZC:
3757 case Mips::BGEZC:
3758 case Mips::BGTZC:
3759 case Mips::BLTZC:
3760 case Mips::BEQZC:
3761 case Mips::BNEZC:
Simon Dardis68a204d2016-07-26 10:25:07 +00003762 case Mips::BLEZC64:
3763 case Mips::BGEZC64:
3764 case Mips::BGTZC64:
3765 case Mips::BLTZC64:
3766 case Mips::BEQZC64:
3767 case Mips::BNEZC64:
3768 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
3769 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00003770 return Match_RequiresNoZeroRegister;
3771 return Match_Success;
3772 case Mips::BGEC:
3773 case Mips::BLTC:
3774 case Mips::BGEUC:
3775 case Mips::BLTUC:
3776 case Mips::BEQC:
3777 case Mips::BNEC:
Simon Dardis68a204d2016-07-26 10:25:07 +00003778 case Mips::BGEC64:
3779 case Mips::BLTC64:
3780 case Mips::BGEUC64:
3781 case Mips::BLTUC64:
3782 case Mips::BEQC64:
3783 case Mips::BNEC64:
3784 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
3785 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00003786 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00003787 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
3788 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00003789 return Match_RequiresNoZeroRegister;
3790 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
3791 return Match_RequiresDifferentOperands;
3792 return Match_Success;
3793 default:
3794 return Match_Success;
3795 }
Matheus Almeida595fcab2014-06-11 15:05:56 +00003796}
3797
Daniel Sanders52da7af2015-11-06 12:11:03 +00003798static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3799 uint64_t ErrorInfo) {
3800 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3801 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3802 if (ErrorLoc == SMLoc())
3803 return Loc;
3804 return ErrorLoc;
3805 }
3806 return Loc;
3807}
3808
David Blaikie960ea3f2014-06-08 16:18:35 +00003809bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3810 OperandVector &Operands,
3811 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003812 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003813 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003814
Jack Carterb4dbc172012-09-05 23:34:03 +00003815 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00003816 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003817 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003818
3819 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003820 case Match_Success: {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003821 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00003822 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003823 return false;
3824 }
3825 case Match_MissingFeature:
3826 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3827 return true;
3828 case Match_InvalidOperand: {
3829 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003830 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003831 if (ErrorInfo >= Operands.size())
3832 return Error(IDLoc, "too few operands for instruction");
3833
Daniel Sanders52da7af2015-11-06 12:11:03 +00003834 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003835 if (ErrorLoc == SMLoc())
3836 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003837 }
3838
3839 return Error(ErrorLoc, "invalid operand for instruction");
3840 }
3841 case Match_MnemonicFail:
3842 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003843 case Match_RequiresDifferentSrcAndDst:
3844 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00003845 case Match_RequiresDifferentOperands:
3846 return Error(IDLoc, "registers must be different");
3847 case Match_RequiresNoZeroRegister:
3848 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00003849 case Match_RequiresSameSrcAndDst:
3850 return Error(IDLoc, "source and destination must match");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003851 case Match_Immz:
3852 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003853 case Match_UImm1_0:
3854 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3855 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003856 case Match_UImm2_0:
3857 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3858 "expected 2-bit unsigned immediate");
3859 case Match_UImm2_1:
3860 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3861 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003862 case Match_UImm3_0:
3863 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3864 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003865 case Match_UImm4_0:
3866 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3867 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003868 case Match_SImm4_0:
3869 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3870 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003871 case Match_UImm5_0:
3872 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3873 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00003874 case Match_SImm5_0:
3875 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3876 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003877 case Match_UImm5_1:
3878 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3879 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003880 case Match_UImm5_32:
3881 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3882 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003883 case Match_UImm5_33:
3884 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3885 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003886 case Match_UImm5_0_Report_UImm6:
3887 // This is used on UImm5 operands that have a corresponding UImm5_32
3888 // operand to avoid confusing the user.
3889 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3890 "expected 6-bit unsigned immediate");
3891 case Match_UImm5_Lsl2:
3892 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3893 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003894 case Match_UImmRange2_64:
3895 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3896 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003897 case Match_UImm6_0:
3898 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3899 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00003900 case Match_UImm6_Lsl2:
3901 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3902 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00003903 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00003904 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3905 "expected 6-bit signed immediate");
3906 case Match_UImm7_0:
3907 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3908 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00003909 case Match_UImm7_N1:
3910 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3911 "expected immediate in range -1 .. 126");
3912 case Match_SImm7_Lsl2:
3913 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3914 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003915 case Match_UImm8_0:
3916 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3917 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003918 case Match_UImm10_0:
3919 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3920 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00003921 case Match_SImm10_0:
3922 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3923 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00003924 case Match_SImm11_0:
3925 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3926 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003927 case Match_UImm16:
3928 case Match_UImm16_Relaxed:
3929 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3930 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003931 case Match_SImm16:
3932 case Match_SImm16_Relaxed:
3933 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3934 "expected 16-bit signed immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003935 case Match_UImm20_0:
3936 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3937 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00003938 case Match_UImm26_0:
3939 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3940 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00003941 case Match_SImm32:
3942 case Match_SImm32_Relaxed:
3943 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3944 "expected 32-bit signed immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00003945 case Match_MemSImm9:
3946 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3947 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00003948 case Match_MemSImm10:
3949 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3950 "expected memory with 10-bit signed offset");
3951 case Match_MemSImm10Lsl1:
3952 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3953 "expected memory with 11-bit signed offset and multiple of 2");
3954 case Match_MemSImm10Lsl2:
3955 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3956 "expected memory with 12-bit signed offset and multiple of 4");
3957 case Match_MemSImm10Lsl3:
3958 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3959 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00003960 case Match_MemSImm11:
3961 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3962 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00003963 case Match_MemSImm12:
3964 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3965 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003966 case Match_MemSImm16:
3967 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3968 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00003969 }
Craig Topper589ceee2015-01-03 08:16:34 +00003970
3971 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003972}
3973
Toma Tabacud9d344b2015-04-27 14:05:04 +00003974void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3975 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3976 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3977 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003978}
3979
Toma Tabacu81496c12015-05-20 08:54:45 +00003980void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3981 if (!AssemblerOptions.back()->isMacro())
3982 Warning(Loc, "macro instruction expanded into multiple instructions");
3983}
3984
Daniel Sandersef638fe2014-10-03 15:37:37 +00003985void
3986MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3987 SMRange Range, bool ShowColors) {
3988 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003989 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003990 ShowColors);
3991}
3992
Jack Carter1ac53222013-02-20 23:11:17 +00003993int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003994 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003995
Vladimir Medic4c299852013-11-06 11:27:05 +00003996 CC = StringSwitch<unsigned>(Name)
3997 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003998 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003999 .Case("a0", 4)
4000 .Case("a1", 5)
4001 .Case("a2", 6)
4002 .Case("a3", 7)
4003 .Case("v0", 2)
4004 .Case("v1", 3)
4005 .Case("s0", 16)
4006 .Case("s1", 17)
4007 .Case("s2", 18)
4008 .Case("s3", 19)
4009 .Case("s4", 20)
4010 .Case("s5", 21)
4011 .Case("s6", 22)
4012 .Case("s7", 23)
4013 .Case("k0", 26)
4014 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004015 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00004016 .Case("sp", 29)
4017 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004018 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00004019 .Case("ra", 31)
4020 .Case("t0", 8)
4021 .Case("t1", 9)
4022 .Case("t2", 10)
4023 .Case("t3", 11)
4024 .Case("t4", 12)
4025 .Case("t5", 13)
4026 .Case("t6", 14)
4027 .Case("t7", 15)
4028 .Case("t8", 24)
4029 .Case("t9", 25)
4030 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004031
Toma Tabacufda445c2014-09-15 15:33:01 +00004032 if (!(isABI_N32() || isABI_N64()))
4033 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004034
Daniel Sandersef638fe2014-10-03 15:37:37 +00004035 if (12 <= CC && CC <= 15) {
4036 // Name is one of t4-t7
4037 AsmToken RegTok = getLexer().peekTok();
4038 SMRange RegRange = RegTok.getLocRange();
4039
4040 StringRef FixedName = StringSwitch<StringRef>(Name)
4041 .Case("t4", "t0")
4042 .Case("t5", "t1")
4043 .Case("t6", "t2")
4044 .Case("t7", "t3")
4045 .Default("");
4046 assert(FixedName != "" && "Register name is not one of t4-t7.");
4047
4048 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
4049 "Did you mean $" + FixedName + "?", RegRange);
4050 }
4051
Toma Tabacufda445c2014-09-15 15:33:01 +00004052 // Although SGI documentation just cuts out t0-t3 for n32/n64,
4053 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
4054 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
4055 if (8 <= CC && CC <= 11)
4056 CC += 4;
4057
4058 if (CC == -1)
4059 CC = StringSwitch<unsigned>(Name)
4060 .Case("a4", 8)
4061 .Case("a5", 9)
4062 .Case("a6", 10)
4063 .Case("a7", 11)
4064 .Case("kt0", 26)
4065 .Case("kt1", 27)
4066 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004067
4068 return CC;
4069}
Jack Carterd0bd6422013-04-18 00:41:53 +00004070
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004071int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
4072 int CC;
4073
4074 CC = StringSwitch<unsigned>(Name)
4075 .Case("hwr_cpunum", 0)
4076 .Case("hwr_synci_step", 1)
4077 .Case("hwr_cc", 2)
4078 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00004079 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004080 .Default(-1);
4081
4082 return CC;
4083}
4084
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004085int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004086
Jack Cartera63b16a2012-09-07 00:23:42 +00004087 if (Name[0] == 'f') {
4088 StringRef NumString = Name.substr(1);
4089 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004090 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004091 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004092 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00004093 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004094 return IntVal;
4095 }
4096 return -1;
4097}
Jack Cartera63b16a2012-09-07 00:23:42 +00004098
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004099int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
4100
4101 if (Name.startswith("fcc")) {
4102 StringRef NumString = Name.substr(3);
4103 unsigned IntVal;
4104 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004105 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004106 if (IntVal > 7) // There are only 8 fcc registers.
4107 return -1;
4108 return IntVal;
4109 }
4110 return -1;
4111}
4112
4113int MipsAsmParser::matchACRegisterName(StringRef Name) {
4114
Akira Hatanaka274d24c2013-08-14 01:15:52 +00004115 if (Name.startswith("ac")) {
4116 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004117 unsigned IntVal;
4118 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004119 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004120 if (IntVal > 3) // There are only 3 acc registers.
4121 return -1;
4122 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00004123 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004124 return -1;
4125}
Jack Carterd0bd6422013-04-18 00:41:53 +00004126
Jack Carter5dc8ac92013-09-25 23:50:44 +00004127int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
4128 unsigned IntVal;
4129
4130 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
4131 return -1;
4132
4133 if (IntVal > 31)
4134 return -1;
4135
4136 return IntVal;
4137}
4138
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004139int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
4140 int CC;
4141
4142 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00004143 .Case("msair", 0)
4144 .Case("msacsr", 1)
4145 .Case("msaaccess", 2)
4146 .Case("msasave", 3)
4147 .Case("msamodify", 4)
4148 .Case("msarequest", 5)
4149 .Case("msamap", 6)
4150 .Case("msaunmap", 7)
4151 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004152
4153 return CC;
4154}
4155
Toma Tabacu89a712b2015-04-15 10:48:56 +00004156unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004157 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004158 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004159 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004160 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004161 return 0;
4162 }
4163 unsigned AT = getReg(
4164 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004165 return AT;
4166}
Jack Carter0b744b32012-10-04 02:29:46 +00004167
Jack Carterd0bd6422013-04-18 00:41:53 +00004168unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004169 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004170}
4171
Toma Tabacu13964452014-09-04 13:23:44 +00004172bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004173 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004174 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004175
Jack Carter30a59822012-10-04 04:03:53 +00004176 // Check if the current operand has a custom associated parser, if so, try to
4177 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004178 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4179 if (ResTy == MatchOperand_Success)
4180 return false;
4181 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4182 // there was a match, but an error occurred, in which case, just return that
4183 // the operand parsing failed.
4184 if (ResTy == MatchOperand_ParseFail)
4185 return true;
4186
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004187 DEBUG(dbgs() << ".. Generic Parser\n");
4188
Jack Carterb4dbc172012-09-05 23:34:03 +00004189 switch (getLexer().getKind()) {
4190 default:
4191 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4192 return true;
4193 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004194 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004195 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004196
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004197 // Almost all registers have been parsed by custom parsers. There is only
4198 // one exception to this. $zero (and it's alias $0) will reach this point
4199 // for div, divu, and similar instructions because it is not an operand
4200 // to the instruction definition but an explicit register. Special case
4201 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004202 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004203 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004204
Jack Carterd0bd6422013-04-18 00:41:53 +00004205 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004206 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004207 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004208 return true;
4209
Jack Carter873c7242013-01-12 01:03:14 +00004210 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004211 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004212 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004213 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004214 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004215
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004216 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004217 return false;
4218 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004219 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004220 case AsmToken::LParen:
4221 case AsmToken::Minus:
4222 case AsmToken::Plus:
4223 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004224 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004225 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004226 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004227 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004228 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004229 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004230 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004231 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004232 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004233 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004234 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004235 return true;
4236
Jack Carter873c7242013-01-12 01:03:14 +00004237 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4238
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004239 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004240 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004241 } // case AsmToken::Percent
4242 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004243 return true;
4244}
4245
Vladimir Medic4c299852013-11-06 11:27:05 +00004246const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004247 StringRef RelocStr) {
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004248 if (RelocStr == "hi(%neg(%gp_rel")
4249 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext());
4250 else if (RelocStr == "lo(%neg(%gp_rel")
4251 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004252
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004253 MipsMCExpr::MipsExprKind Kind =
4254 StringSwitch<MipsMCExpr::MipsExprKind>(RelocStr)
4255 .Case("call16", MipsMCExpr::MEK_GOT_CALL)
4256 .Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
4257 .Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
4258 .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
4259 .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
4260 .Case("got", MipsMCExpr::MEK_GOT)
4261 .Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
4262 .Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
4263 .Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
4264 .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
4265 .Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
4266 .Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
4267 .Case("gp_rel", MipsMCExpr::MEK_GPREL)
4268 .Case("hi", MipsMCExpr::MEK_HI)
4269 .Case("higher", MipsMCExpr::MEK_HIGHER)
4270 .Case("highest", MipsMCExpr::MEK_HIGHEST)
4271 .Case("lo", MipsMCExpr::MEK_LO)
4272 .Case("neg", MipsMCExpr::MEK_NEG)
4273 .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
4274 .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
4275 .Case("tlsgd", MipsMCExpr::MEK_TLSGD)
4276 .Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
4277 .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
4278 .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
4279 .Default(MipsMCExpr::MEK_None);
Jack Carterb5cf5902013-04-17 00:18:04 +00004280
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004281 assert(Kind != MipsMCExpr::MEK_None);
4282 return MipsMCExpr::create(Kind, Expr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004283}
4284
4285bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4286
4287 switch (Expr->getKind()) {
4288 case MCExpr::Constant:
4289 return true;
4290 case MCExpr::SymbolRef:
4291 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4292 case MCExpr::Binary:
4293 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4294 if (!isEvaluated(BE->getLHS()))
4295 return false;
4296 return isEvaluated(BE->getRHS());
4297 }
4298 case MCExpr::Unary:
4299 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004300 case MCExpr::Target:
4301 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004302 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004303 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004304}
Jack Carterd0bd6422013-04-18 00:41:53 +00004305
Jack Carterb5cf5902013-04-17 00:18:04 +00004306bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004307 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004308 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004309 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004310 if (Tok.isNot(AsmToken::Identifier))
4311 return true;
4312
Yaron Keren075759a2015-03-30 15:42:36 +00004313 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004314
Jack Carterd0bd6422013-04-18 00:41:53 +00004315 Parser.Lex(); // Eat the identifier.
4316 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004317 const MCExpr *IdVal;
4318 SMLoc EndLoc;
4319
4320 if (getLexer().getKind() == AsmToken::LParen) {
4321 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004322 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004323 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004324 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004325 const AsmToken &nextTok = Parser.getTok();
4326 if (nextTok.isNot(AsmToken::Identifier))
4327 return true;
4328 Str += "(%";
4329 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004330 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004331 if (getLexer().getKind() != AsmToken::LParen)
4332 return true;
4333 } else
4334 break;
4335 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004336 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004337 return true;
4338
4339 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004340 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004341
4342 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004343 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004344
Jack Carterd0bd6422013-04-18 00:41:53 +00004345 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004346 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004347}
4348
Jack Carterb4dbc172012-09-05 23:34:03 +00004349bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4350 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004351 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004352 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004353 if (ResTy == MatchOperand_Success) {
4354 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004355 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004356 StartLoc = Operand.getStartLoc();
4357 EndLoc = Operand.getEndLoc();
4358
4359 // AFAIK, we only support numeric registers and named GPR's in CFI
4360 // directives.
4361 // Don't worry about eating tokens before failing. Using an unrecognised
4362 // register is a parse error.
4363 if (Operand.isGPRAsmReg()) {
4364 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004365 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004366 }
4367
4368 return (RegNo == (unsigned)-1);
4369 }
4370
4371 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004372 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004373}
4374
Jack Carterb5cf5902013-04-17 00:18:04 +00004375bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004376 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004377 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004378 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004379 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004380
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004381 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004382 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004383 ++NumOfLParen;
4384 }
Jack Carter873c7242013-01-12 01:03:14 +00004385
Jack Carterd0bd6422013-04-18 00:41:53 +00004386 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004387 default:
4388 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004389 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004390 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004391 case AsmToken::Integer:
4392 case AsmToken::Minus:
4393 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004394 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004395 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004396 else
4397 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004398 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004399 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004400 break;
Jack Carter873c7242013-01-12 01:03:14 +00004401 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004402 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004403 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004404 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004405}
4406
David Blaikie960ea3f2014-06-08 16:18:35 +00004407MipsAsmParser::OperandMatchResultTy
4408MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004409 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004410 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004411 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004412 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004413 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004414 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004415 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004416 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004417
Jack Carterb5cf5902013-04-17 00:18:04 +00004418 if (getLexer().getKind() == AsmToken::LParen) {
4419 Parser.Lex();
4420 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004421 }
4422
Jack Carterb5cf5902013-04-17 00:18:04 +00004423 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004424 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004425 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004426
Jack Carterd0bd6422013-04-18 00:41:53 +00004427 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004428 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004429 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004430 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004431 SMLoc E =
4432 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004433 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004434 return MatchOperand_Success;
4435 }
4436 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004437 SMLoc E =
4438 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004439
Jack Carterd0bd6422013-04-18 00:41:53 +00004440 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004441 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00004442 auto Base = MipsOperand::createGPRReg(
4443 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00004444 Operands.push_back(
4445 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004446 return MatchOperand_Success;
4447 }
4448 Error(Parser.getTok().getLoc(), "'(' expected");
4449 return MatchOperand_ParseFail;
4450 }
4451
Jack Carterd0bd6422013-04-18 00:41:53 +00004452 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004453 }
4454
Toma Tabacu13964452014-09-04 13:23:44 +00004455 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004456 if (Res != MatchOperand_Success)
4457 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004458
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004459 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004460 Error(Parser.getTok().getLoc(), "')' expected");
4461 return MatchOperand_ParseFail;
4462 }
4463
Jack Carter873c7242013-01-12 01:03:14 +00004464 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4465
Jack Carterd0bd6422013-04-18 00:41:53 +00004466 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004467
Craig Topper062a2ba2014-04-25 05:30:21 +00004468 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004469 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004470
Jack Carterd0bd6422013-04-18 00:41:53 +00004471 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004472 std::unique_ptr<MipsOperand> op(
4473 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004474 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004475 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004476 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004477 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004478 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4479 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004480 if (IdVal->evaluateAsAbsolute(Imm))
4481 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004482 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004483 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004484 getContext());
4485 }
4486
David Blaikie960ea3f2014-06-08 16:18:35 +00004487 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004488 return MatchOperand_Success;
4489}
4490
David Blaikie960ea3f2014-06-08 16:18:35 +00004491bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004492 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004493 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004494 if (Sym) {
4495 SMLoc S = Parser.getTok().getLoc();
4496 const MCExpr *Expr;
4497 if (Sym->isVariable())
4498 Expr = Sym->getVariableValue();
4499 else
4500 return false;
4501 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004502 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004503 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004504 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004505 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004506 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004507 if (ResTy == MatchOperand_Success) {
4508 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004509 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004510 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004511 llvm_unreachable("Should never ParseFail");
4512 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004513 }
Jack Carterd76b2372013-03-21 21:44:16 +00004514 }
4515 }
4516 return false;
4517}
Jack Carterd0bd6422013-04-18 00:41:53 +00004518
Jack Carter873c7242013-01-12 01:03:14 +00004519MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004520MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004521 StringRef Identifier,
4522 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004523 int Index = matchCPURegisterName(Identifier);
4524 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004525 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004526 Index, Identifier, getContext().getRegisterInfo(), S,
4527 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004528 return MatchOperand_Success;
4529 }
4530
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004531 Index = matchHWRegsRegisterName(Identifier);
4532 if (Index != -1) {
4533 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004534 Index, Identifier, getContext().getRegisterInfo(), S,
4535 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004536 return MatchOperand_Success;
4537 }
4538
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004539 Index = matchFPURegisterName(Identifier);
4540 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004541 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004542 Index, Identifier, getContext().getRegisterInfo(), S,
4543 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004544 return MatchOperand_Success;
4545 }
4546
4547 Index = matchFCCRegisterName(Identifier);
4548 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004549 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004550 Index, Identifier, getContext().getRegisterInfo(), S,
4551 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004552 return MatchOperand_Success;
4553 }
4554
4555 Index = matchACRegisterName(Identifier);
4556 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004557 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004558 Index, Identifier, getContext().getRegisterInfo(), S,
4559 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004560 return MatchOperand_Success;
4561 }
4562
4563 Index = matchMSA128RegisterName(Identifier);
4564 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004565 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004566 Index, Identifier, getContext().getRegisterInfo(), S,
4567 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004568 return MatchOperand_Success;
4569 }
4570
4571 Index = matchMSA128CtrlRegisterName(Identifier);
4572 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004573 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004574 Index, Identifier, getContext().getRegisterInfo(), S,
4575 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004576 return MatchOperand_Success;
4577 }
4578
4579 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004580}
4581
4582MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004583MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004584 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004585 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004586
4587 if (Token.is(AsmToken::Identifier)) {
4588 DEBUG(dbgs() << ".. identifier\n");
4589 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004590 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004591 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004592 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004593 } else if (Token.is(AsmToken::Integer)) {
4594 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004595 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004596 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
4597 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004598 return MatchOperand_Success;
4599 }
4600
4601 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4602
4603 return MatchOperand_NoMatch;
4604}
4605
David Blaikie960ea3f2014-06-08 16:18:35 +00004606MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004607MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004608 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004609 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004610
4611 auto Token = Parser.getTok();
4612
4613 SMLoc S = Token.getLoc();
4614
4615 if (Token.isNot(AsmToken::Dollar)) {
4616 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4617 if (Token.is(AsmToken::Identifier)) {
4618 if (searchSymbolAlias(Operands))
4619 return MatchOperand_Success;
4620 }
4621 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4622 return MatchOperand_NoMatch;
4623 }
4624 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004625
Toma Tabacu13964452014-09-04 13:23:44 +00004626 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004627 if (ResTy == MatchOperand_Success) {
4628 Parser.Lex(); // $
4629 Parser.Lex(); // identifier
4630 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004631 return ResTy;
4632}
4633
4634MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004635MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004636 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004637 switch (getLexer().getKind()) {
4638 default:
4639 return MatchOperand_NoMatch;
4640 case AsmToken::LParen:
4641 case AsmToken::Minus:
4642 case AsmToken::Plus:
4643 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004644 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004645 case AsmToken::String:
4646 break;
4647 }
4648
4649 const MCExpr *IdVal;
4650 SMLoc S = Parser.getTok().getLoc();
4651 if (getParser().parseExpression(IdVal))
4652 return MatchOperand_ParseFail;
4653
4654 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4655 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4656 return MatchOperand_Success;
4657}
4658
David Blaikie960ea3f2014-06-08 16:18:35 +00004659MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004660MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004661 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004662 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004663
4664 SMLoc S = getLexer().getLoc();
4665
4666 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004667 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004668 if (ResTy != MatchOperand_NoMatch)
4669 return ResTy;
4670
Daniel Sanders315386c2014-04-01 10:40:14 +00004671 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004672 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004673 if (ResTy != MatchOperand_NoMatch)
4674 return ResTy;
4675
Daniel Sandersffd84362014-04-01 10:41:48 +00004676 const MCExpr *Expr = nullptr;
4677 if (Parser.parseExpression(Expr)) {
4678 // We have no way of knowing if a symbol was consumed so we must ParseFail
4679 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004680 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004681 Operands.push_back(
4682 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004683 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004684}
4685
Vladimir Medic2b953d02013-10-01 09:48:56 +00004686MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004687MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004688 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004689 const MCExpr *IdVal;
4690 // If the first token is '$' we may have register operand.
4691 if (Parser.getTok().is(AsmToken::Dollar))
4692 return MatchOperand_NoMatch;
4693 SMLoc S = Parser.getTok().getLoc();
4694 if (getParser().parseExpression(IdVal))
4695 return MatchOperand_ParseFail;
4696 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004697 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004698 int64_t Val = MCE->getValue();
4699 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4700 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004701 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004702 return MatchOperand_Success;
4703}
4704
Matheus Almeida779c5932013-11-18 12:32:49 +00004705MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004706MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4707 MCAsmParser &Parser = getParser();
4708 SmallVector<unsigned, 10> Regs;
4709 unsigned RegNo;
4710 unsigned PrevReg = Mips::NoRegister;
4711 bool RegRange = false;
4712 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4713
4714 if (Parser.getTok().isNot(AsmToken::Dollar))
4715 return MatchOperand_ParseFail;
4716
4717 SMLoc S = Parser.getTok().getLoc();
4718 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4719 SMLoc E = getLexer().getLoc();
4720 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4721 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4722 if (RegRange) {
4723 // Remove last register operand because registers from register range
4724 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004725 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4726 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004727 Regs.push_back(RegNo);
4728 } else {
4729 unsigned TmpReg = PrevReg + 1;
4730 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004731 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4732 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4733 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004734 Error(E, "invalid register operand");
4735 return MatchOperand_ParseFail;
4736 }
4737
4738 PrevReg = TmpReg;
4739 Regs.push_back(TmpReg++);
4740 }
4741 }
4742
4743 RegRange = false;
4744 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004745 if ((PrevReg == Mips::NoRegister) &&
4746 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4747 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004748 Error(E, "$16 or $31 expected");
4749 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004750 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4751 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4752 !isGP64bit()) ||
4753 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4754 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4755 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004756 Error(E, "invalid register operand");
4757 return MatchOperand_ParseFail;
4758 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004759 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4760 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4761 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004762 Error(E, "consecutive register numbers expected");
4763 return MatchOperand_ParseFail;
4764 }
4765
4766 Regs.push_back(RegNo);
4767 }
4768
4769 if (Parser.getTok().is(AsmToken::Minus))
4770 RegRange = true;
4771
4772 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4773 !Parser.getTok().isNot(AsmToken::Comma)) {
4774 Error(E, "',' or '-' expected");
4775 return MatchOperand_ParseFail;
4776 }
4777
4778 Lex(); // Consume comma or minus
4779 if (Parser.getTok().isNot(AsmToken::Dollar))
4780 break;
4781
4782 PrevReg = RegNo;
4783 }
4784
4785 SMLoc E = Parser.getTok().getLoc();
4786 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4787 parseMemOperand(Operands);
4788 return MatchOperand_Success;
4789}
4790
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004791MipsAsmParser::OperandMatchResultTy
4792MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4793 MCAsmParser &Parser = getParser();
4794
4795 SMLoc S = Parser.getTok().getLoc();
4796 if (parseAnyRegister(Operands) != MatchOperand_Success)
4797 return MatchOperand_ParseFail;
4798
4799 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00004800 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00004801
Benjamin Kramer2b68d152016-05-09 10:31:17 +00004802 Operands.pop_back();
4803 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004804 return MatchOperand_Success;
4805}
4806
Zoran Jovanovic41688672015-02-10 16:36:20 +00004807MipsAsmParser::OperandMatchResultTy
4808MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4809 MCAsmParser &Parser = getParser();
4810 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4811 SmallVector<unsigned, 10> Regs;
4812
4813 if (Parser.getTok().isNot(AsmToken::Dollar))
4814 return MatchOperand_ParseFail;
4815
4816 SMLoc S = Parser.getTok().getLoc();
4817
4818 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4819 return MatchOperand_ParseFail;
4820
4821 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4822 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4823 Regs.push_back(RegNo);
4824
4825 SMLoc E = Parser.getTok().getLoc();
4826 if (Parser.getTok().isNot(AsmToken::Comma)) {
4827 Error(E, "',' expected");
4828 return MatchOperand_ParseFail;
4829 }
4830
4831 // Remove comma.
4832 Parser.Lex();
4833
4834 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4835 return MatchOperand_ParseFail;
4836
4837 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4838 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4839 Regs.push_back(RegNo);
4840
4841 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4842
4843 return MatchOperand_Success;
4844}
4845
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004846/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4847/// either this.
4848/// ::= '(', register, ')'
4849/// handle it before we iterate so we don't get tripped up by the lack of
4850/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004851bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004852 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004853 if (getLexer().is(AsmToken::LParen)) {
4854 Operands.push_back(
4855 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4856 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004857 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004858 SMLoc Loc = getLexer().getLoc();
4859 Parser.eatToEndOfStatement();
4860 return Error(Loc, "unexpected token in argument list");
4861 }
4862 if (Parser.getTok().isNot(AsmToken::RParen)) {
4863 SMLoc Loc = getLexer().getLoc();
4864 Parser.eatToEndOfStatement();
4865 return Error(Loc, "unexpected token, expected ')'");
4866 }
4867 Operands.push_back(
4868 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4869 Parser.Lex();
4870 }
4871 return false;
4872}
4873
4874/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4875/// either one of these.
4876/// ::= '[', register, ']'
4877/// ::= '[', integer, ']'
4878/// handle it before we iterate so we don't get tripped up by the lack of
4879/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004880bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004881 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004882 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004883 if (getLexer().is(AsmToken::LBrac)) {
4884 Operands.push_back(
4885 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4886 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004887 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004888 SMLoc Loc = getLexer().getLoc();
4889 Parser.eatToEndOfStatement();
4890 return Error(Loc, "unexpected token in argument list");
4891 }
4892 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4893 SMLoc Loc = getLexer().getLoc();
4894 Parser.eatToEndOfStatement();
4895 return Error(Loc, "unexpected token, expected ']'");
4896 }
4897 Operands.push_back(
4898 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4899 Parser.Lex();
4900 }
4901 return false;
4902}
4903
David Blaikie960ea3f2014-06-08 16:18:35 +00004904bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4905 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004906 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004907 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004908
4909 // We have reached first instruction, module directive are now forbidden.
4910 getTargetStreamer().forbidModuleDirective();
4911
Vladimir Medic74593e62013-07-17 15:00:42 +00004912 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004913 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004914 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004915 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004916 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004917 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004918 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004919
4920 // Read the remaining operands.
4921 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4922 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004923 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004924 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004925 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004926 return Error(Loc, "unexpected token in argument list");
4927 }
Toma Tabacu13964452014-09-04 13:23:44 +00004928 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004929 return true;
4930 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004931
Jack Carterd0bd6422013-04-18 00:41:53 +00004932 while (getLexer().is(AsmToken::Comma)) {
4933 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004934 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004935 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004936 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004937 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004938 return Error(Loc, "unexpected token in argument list");
4939 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004940 // Parse bracket and parenthesis suffixes before we iterate
4941 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004942 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004943 return true;
4944 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004945 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004946 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004947 }
4948 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004949 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4950 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004951 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004952 return Error(Loc, "unexpected token in argument list");
4953 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004954 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004955 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004956}
4957
Nirav Dave996fc132016-05-05 14:15:46 +00004958// FIXME: Given that these have the same name, these should both be
4959// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004960bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004961 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004962 SMLoc Loc = getLexer().getLoc();
4963 Parser.eatToEndOfStatement();
4964 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004965}
4966
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004967bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004968 return Error(Loc, ErrorMsg);
4969}
4970
Jack Carter0b744b32012-10-04 02:29:46 +00004971bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004972 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004973 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004974
4975 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004976 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004977
4978 Parser.Lex(); // Eat "noat".
4979
Jack Carterd0bd6422013-04-18 00:41:53 +00004980 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004981 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004982 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004983 return false;
4984 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004985
4986 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004987 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004988 return false;
4989}
Jack Carterd0bd6422013-04-18 00:41:53 +00004990
Jack Carter0b744b32012-10-04 02:29:46 +00004991bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004992 // Line can be: ".set at", which sets $at to $1
4993 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004994 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004995 Parser.Lex(); // Eat "at".
4996
Jack Carter0b744b32012-10-04 02:29:46 +00004997 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004998 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004999 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00005000
5001 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005002 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005003 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00005004 }
5005
5006 if (getLexer().isNot(AsmToken::Equal)) {
5007 reportParseError("unexpected token, expected equals sign");
5008 return false;
5009 }
5010 Parser.Lex(); // Eat "=".
5011
5012 if (getLexer().isNot(AsmToken::Dollar)) {
5013 if (getLexer().is(AsmToken::EndOfStatement)) {
5014 reportParseError("no register specified");
5015 return false;
5016 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00005017 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00005018 return false;
5019 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005020 }
5021 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00005022
Toma Tabacu16a74492015-02-13 10:30:57 +00005023 // Find out what "reg" is.
5024 unsigned AtRegNo;
5025 const AsmToken &Reg = Parser.getTok();
5026 if (Reg.is(AsmToken::Identifier)) {
5027 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
5028 } else if (Reg.is(AsmToken::Integer)) {
5029 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00005030 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00005031 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00005032 return false;
5033 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005034
5035 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00005036 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005037 reportParseError("invalid register");
5038 return false;
5039 }
5040 Parser.Lex(); // Eat "reg".
5041
5042 // If this is not the end of the statement, report an error.
5043 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5044 reportParseError("unexpected token, expected end of statement");
5045 return false;
5046 }
5047
5048 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
5049
5050 Parser.Lex(); // Consume the EndOfStatement.
5051 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005052}
5053
5054bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005055 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005056 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005057 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005058 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005059 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005060 return false;
5061 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005062 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00005063 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005064 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005065 return false;
5066}
5067
5068bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005069 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005070 Parser.Lex();
5071 // If this is not the end of the statement, report an error.
5072 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005073 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005074 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005075 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005076 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005077 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005078 Parser.Lex(); // Consume the EndOfStatement.
5079 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005080}
5081
5082bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005083 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005084 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005085 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005086 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005087 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005088 return false;
5089 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005090 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005091 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005092 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005093 return false;
5094}
5095
5096bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005097 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005098 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005099 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005100 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005101 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005102 return false;
5103 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005104 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005105 reportParseError("`noreorder' must be set before `nomacro'");
5106 return false;
5107 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005108 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005109 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005110 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005111 return false;
5112}
Jack Carterd76b2372013-03-21 21:44:16 +00005113
Daniel Sanders44934432014-08-07 12:03:36 +00005114bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005115 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005116 Parser.Lex();
5117
5118 // If this is not the end of the statement, report an error.
5119 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005120 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005121
5122 setFeatureBits(Mips::FeatureMSA, "msa");
5123 getTargetStreamer().emitDirectiveSetMsa();
5124 return false;
5125}
5126
5127bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005128 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005129 Parser.Lex();
5130
5131 // If this is not the end of the statement, report an error.
5132 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005133 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005134
5135 clearFeatureBits(Mips::FeatureMSA, "msa");
5136 getTargetStreamer().emitDirectiveSetNoMsa();
5137 return false;
5138}
5139
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005140bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005141 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005142 Parser.Lex(); // Eat "nodsp".
5143
5144 // If this is not the end of the statement, report an error.
5145 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5146 reportParseError("unexpected token, expected end of statement");
5147 return false;
5148 }
5149
5150 clearFeatureBits(Mips::FeatureDSP, "dsp");
5151 getTargetStreamer().emitDirectiveSetNoDsp();
5152 return false;
5153}
5154
Toma Tabacucc2502d2014-11-04 17:18:07 +00005155bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005156 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005157 Parser.Lex(); // Eat "mips16".
5158
Jack Carter39536722014-01-22 23:08:42 +00005159 // If this is not the end of the statement, report an error.
5160 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005161 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005162 return false;
5163 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005164
5165 setFeatureBits(Mips::FeatureMips16, "mips16");
5166 getTargetStreamer().emitDirectiveSetMips16();
5167 Parser.Lex(); // Consume the EndOfStatement.
5168 return false;
5169}
5170
5171bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005172 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005173 Parser.Lex(); // Eat "nomips16".
5174
5175 // If this is not the end of the statement, report an error.
5176 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5177 reportParseError("unexpected token, expected end of statement");
5178 return false;
5179 }
5180
5181 clearFeatureBits(Mips::FeatureMips16, "mips16");
5182 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005183 Parser.Lex(); // Consume the EndOfStatement.
5184 return false;
5185}
5186
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005187bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005188 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005189 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005190 // Line can be: .set fp=32
5191 // .set fp=xx
5192 // .set fp=64
5193 Parser.Lex(); // Eat fp token
5194 AsmToken Tok = Parser.getTok();
5195 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005196 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005197 return false;
5198 }
5199 Parser.Lex(); // Eat '=' token.
5200 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005201
5202 if (!parseFpABIValue(FpAbiVal, ".set"))
5203 return false;
5204
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005205 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005206 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005207 return false;
5208 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005209 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005210 Parser.Lex(); // Consume the EndOfStatement.
5211 return false;
5212}
5213
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005214bool MipsAsmParser::parseSetOddSPRegDirective() {
5215 MCAsmParser &Parser = getParser();
5216
5217 Parser.Lex(); // Eat "oddspreg".
5218 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5219 reportParseError("unexpected token, expected end of statement");
5220 return false;
5221 }
5222
5223 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5224 getTargetStreamer().emitDirectiveSetOddSPReg();
5225 return false;
5226}
5227
5228bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5229 MCAsmParser &Parser = getParser();
5230
5231 Parser.Lex(); // Eat "nooddspreg".
5232 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5233 reportParseError("unexpected token, expected end of statement");
5234 return false;
5235 }
5236
5237 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5238 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5239 return false;
5240}
5241
Toma Tabacu9db22db2014-09-09 10:15:38 +00005242bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005243 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005244 SMLoc Loc = getLexer().getLoc();
5245
5246 Parser.Lex();
5247 if (getLexer().isNot(AsmToken::EndOfStatement))
5248 return reportParseError("unexpected token, expected end of statement");
5249
5250 // Always keep an element on the options "stack" to prevent the user
5251 // from changing the initial options. This is how we remember them.
5252 if (AssemblerOptions.size() == 2)
5253 return reportParseError(Loc, ".set pop with no .set push");
5254
Akira Hatanakab11ef082015-11-14 06:35:56 +00005255 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005256 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005257 setAvailableFeatures(
5258 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5259 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005260
5261 getTargetStreamer().emitDirectiveSetPop();
5262 return false;
5263}
5264
5265bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005266 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005267 Parser.Lex();
5268 if (getLexer().isNot(AsmToken::EndOfStatement))
5269 return reportParseError("unexpected token, expected end of statement");
5270
5271 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005272 AssemblerOptions.push_back(
5273 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005274
5275 getTargetStreamer().emitDirectiveSetPush();
5276 return false;
5277}
5278
Toma Tabacu29696502015-06-02 09:48:04 +00005279bool MipsAsmParser::parseSetSoftFloatDirective() {
5280 MCAsmParser &Parser = getParser();
5281 Parser.Lex();
5282 if (getLexer().isNot(AsmToken::EndOfStatement))
5283 return reportParseError("unexpected token, expected end of statement");
5284
5285 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5286 getTargetStreamer().emitDirectiveSetSoftFloat();
5287 return false;
5288}
5289
5290bool MipsAsmParser::parseSetHardFloatDirective() {
5291 MCAsmParser &Parser = getParser();
5292 Parser.Lex();
5293 if (getLexer().isNot(AsmToken::EndOfStatement))
5294 return reportParseError("unexpected token, expected end of statement");
5295
5296 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5297 getTargetStreamer().emitDirectiveSetHardFloat();
5298 return false;
5299}
5300
Jack Carterd76b2372013-03-21 21:44:16 +00005301bool MipsAsmParser::parseSetAssignment() {
5302 StringRef Name;
5303 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005304 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005305
5306 if (Parser.parseIdentifier(Name))
5307 reportParseError("expected identifier after .set");
5308
5309 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005310 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005311 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005312
Jack Carter3b2c96e2014-01-22 23:31:38 +00005313 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005314 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005315
Jim Grosbach6f482002015-05-18 18:43:14 +00005316 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005317 Sym->setVariableValue(Value);
5318
5319 return false;
5320}
Jack Carterd0bd6422013-04-18 00:41:53 +00005321
Toma Tabacu26647792014-09-09 12:52:14 +00005322bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005323 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005324 Parser.Lex();
5325 if (getLexer().isNot(AsmToken::EndOfStatement))
5326 return reportParseError("unexpected token, expected end of statement");
5327
5328 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005329 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005330 setAvailableFeatures(
5331 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5332 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005333 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5334
5335 getTargetStreamer().emitDirectiveSetMips0();
5336 return false;
5337}
5338
Toma Tabacu85618b32014-08-19 14:22:52 +00005339bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005340 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005341 Parser.Lex();
5342 if (getLexer().isNot(AsmToken::Equal))
5343 return reportParseError("unexpected token, expected equals sign");
5344
5345 Parser.Lex();
5346 StringRef Arch;
5347 if (Parser.parseIdentifier(Arch))
5348 return reportParseError("expected arch identifier");
5349
5350 StringRef ArchFeatureName =
5351 StringSwitch<StringRef>(Arch)
5352 .Case("mips1", "mips1")
5353 .Case("mips2", "mips2")
5354 .Case("mips3", "mips3")
5355 .Case("mips4", "mips4")
5356 .Case("mips5", "mips5")
5357 .Case("mips32", "mips32")
5358 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005359 .Case("mips32r3", "mips32r3")
5360 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005361 .Case("mips32r6", "mips32r6")
5362 .Case("mips64", "mips64")
5363 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005364 .Case("mips64r3", "mips64r3")
5365 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005366 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005367 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005368 .Case("r4000", "mips3") // This is an implementation of Mips3.
5369 .Default("");
5370
5371 if (ArchFeatureName.empty())
5372 return reportParseError("unsupported architecture");
5373
5374 selectArch(ArchFeatureName);
5375 getTargetStreamer().emitDirectiveSetArch(Arch);
5376 return false;
5377}
5378
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005379bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005380 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005381 Parser.Lex();
5382 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005383 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005384
Matheus Almeida2852af82014-04-22 10:15:54 +00005385 switch (Feature) {
5386 default:
5387 llvm_unreachable("Unimplemented feature");
5388 case Mips::FeatureDSP:
5389 setFeatureBits(Mips::FeatureDSP, "dsp");
5390 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005391 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005392 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00005393 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00005394 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005395 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005396 case Mips::FeatureMips1:
5397 selectArch("mips1");
5398 getTargetStreamer().emitDirectiveSetMips1();
5399 break;
5400 case Mips::FeatureMips2:
5401 selectArch("mips2");
5402 getTargetStreamer().emitDirectiveSetMips2();
5403 break;
5404 case Mips::FeatureMips3:
5405 selectArch("mips3");
5406 getTargetStreamer().emitDirectiveSetMips3();
5407 break;
5408 case Mips::FeatureMips4:
5409 selectArch("mips4");
5410 getTargetStreamer().emitDirectiveSetMips4();
5411 break;
5412 case Mips::FeatureMips5:
5413 selectArch("mips5");
5414 getTargetStreamer().emitDirectiveSetMips5();
5415 break;
5416 case Mips::FeatureMips32:
5417 selectArch("mips32");
5418 getTargetStreamer().emitDirectiveSetMips32();
5419 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005420 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005421 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005422 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005423 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005424 case Mips::FeatureMips32r3:
5425 selectArch("mips32r3");
5426 getTargetStreamer().emitDirectiveSetMips32R3();
5427 break;
5428 case Mips::FeatureMips32r5:
5429 selectArch("mips32r5");
5430 getTargetStreamer().emitDirectiveSetMips32R5();
5431 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005432 case Mips::FeatureMips32r6:
5433 selectArch("mips32r6");
5434 getTargetStreamer().emitDirectiveSetMips32R6();
5435 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005436 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005437 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005438 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005439 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005440 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005441 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005442 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005443 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005444 case Mips::FeatureMips64r3:
5445 selectArch("mips64r3");
5446 getTargetStreamer().emitDirectiveSetMips64R3();
5447 break;
5448 case Mips::FeatureMips64r5:
5449 selectArch("mips64r5");
5450 getTargetStreamer().emitDirectiveSetMips64R5();
5451 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005452 case Mips::FeatureMips64r6:
5453 selectArch("mips64r6");
5454 getTargetStreamer().emitDirectiveSetMips64R6();
5455 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005456 }
5457 return false;
5458}
5459
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005460bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005461 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005462 if (getLexer().isNot(AsmToken::Comma)) {
5463 SMLoc Loc = getLexer().getLoc();
5464 Parser.eatToEndOfStatement();
5465 return Error(Loc, ErrorStr);
5466 }
5467
Matheus Almeida2852af82014-04-22 10:15:54 +00005468 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005469 return true;
5470}
5471
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005472// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5473// In this class, it is only used for .cprestore.
5474// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5475// MipsTargetELFStreamer and MipsAsmParser.
5476bool MipsAsmParser::isPicAndNotNxxAbi() {
5477 return inPicMode() && !(isABI_N32() || isABI_N64());
5478}
5479
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005480bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005481 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005482 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005483
Toma Tabacudde4c462014-11-06 10:02:45 +00005484 if (inMips16Mode()) {
5485 reportParseError(".cpload is not supported in Mips16 mode");
5486 return false;
5487 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005488
David Blaikie960ea3f2014-06-08 16:18:35 +00005489 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005490 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005491 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5492 reportParseError("expected register containing function address");
5493 return false;
5494 }
5495
David Blaikie960ea3f2014-06-08 16:18:35 +00005496 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5497 if (!RegOpnd.isGPRAsmReg()) {
5498 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005499 return false;
5500 }
5501
Toma Tabacudde4c462014-11-06 10:02:45 +00005502 // If this is not the end of the statement, report an error.
5503 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5504 reportParseError("unexpected token, expected end of statement");
5505 return false;
5506 }
5507
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005508 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005509 return false;
5510}
5511
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005512bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5513 MCAsmParser &Parser = getParser();
5514
5515 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5516 // is used in non-PIC mode.
5517
5518 if (inMips16Mode()) {
5519 reportParseError(".cprestore is not supported in Mips16 mode");
5520 return false;
5521 }
5522
5523 // Get the stack offset value.
5524 const MCExpr *StackOffset;
5525 int64_t StackOffsetVal;
5526 if (Parser.parseExpression(StackOffset)) {
5527 reportParseError("expected stack offset value");
5528 return false;
5529 }
5530
5531 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5532 reportParseError("stack offset is not an absolute expression");
5533 return false;
5534 }
5535
5536 if (StackOffsetVal < 0) {
5537 Warning(Loc, ".cprestore with negative stack offset has no effect");
5538 IsCpRestoreSet = false;
5539 } else {
5540 IsCpRestoreSet = true;
5541 CpRestoreOffset = StackOffsetVal;
5542 }
5543
5544 // If this is not the end of the statement, report an error.
5545 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5546 reportParseError("unexpected token, expected end of statement");
5547 return false;
5548 }
5549
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005550 if (!getTargetStreamer().emitDirectiveCpRestore(
5551 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005552 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005553 Parser.Lex(); // Consume the EndOfStatement.
5554 return false;
5555}
5556
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005557bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005558 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005559 unsigned FuncReg;
5560 unsigned Save;
5561 bool SaveIsReg = true;
5562
Matheus Almeida7e815762014-06-18 13:08:59 +00005563 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005564 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005565 if (ResTy == MatchOperand_NoMatch) {
5566 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005567 return false;
5568 }
5569
5570 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5571 if (!FuncRegOpnd.isGPRAsmReg()) {
5572 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5573 Parser.eatToEndOfStatement();
5574 return false;
5575 }
5576
5577 FuncReg = FuncRegOpnd.getGPR32Reg();
5578 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005579
Toma Tabacu65f10572014-09-16 15:00:52 +00005580 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005581 return true;
5582
Toma Tabacu13964452014-09-04 13:23:44 +00005583 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005584 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005585 const MCExpr *OffsetExpr;
5586 int64_t OffsetVal;
5587 SMLoc ExprLoc = getLexer().getLoc();
5588
5589 if (Parser.parseExpression(OffsetExpr) ||
5590 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5591 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005592 Parser.eatToEndOfStatement();
5593 return false;
5594 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005595
5596 Save = OffsetVal;
5597 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005598 } else {
5599 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5600 if (!SaveOpnd.isGPRAsmReg()) {
5601 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5602 Parser.eatToEndOfStatement();
5603 return false;
5604 }
5605 Save = SaveOpnd.getGPR32Reg();
5606 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005607
Toma Tabacu65f10572014-09-16 15:00:52 +00005608 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005609 return true;
5610
Toma Tabacu8874eac2015-02-18 13:46:53 +00005611 const MCExpr *Expr;
5612 if (Parser.parseExpression(Expr)) {
5613 reportParseError("expected expression");
5614 return false;
5615 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005616
Toma Tabacu8874eac2015-02-18 13:46:53 +00005617 if (Expr->getKind() != MCExpr::SymbolRef) {
5618 reportParseError("expected symbol");
5619 return false;
5620 }
5621 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5622
Daniel Sandersf173dda2015-09-22 10:50:09 +00005623 CpSaveLocation = Save;
5624 CpSaveLocationIsRegister = SaveIsReg;
5625
Toma Tabacu8874eac2015-02-18 13:46:53 +00005626 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5627 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005628 return false;
5629}
5630
Daniel Sandersf173dda2015-09-22 10:50:09 +00005631bool MipsAsmParser::parseDirectiveCPReturn() {
5632 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5633 CpSaveLocationIsRegister);
5634 return false;
5635}
5636
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005637bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005638 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005639 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5640 const AsmToken &Tok = Parser.getTok();
5641
5642 if (Tok.getString() == "2008") {
5643 Parser.Lex();
5644 getTargetStreamer().emitDirectiveNaN2008();
5645 return false;
5646 } else if (Tok.getString() == "legacy") {
5647 Parser.Lex();
5648 getTargetStreamer().emitDirectiveNaNLegacy();
5649 return false;
5650 }
5651 }
5652 // If we don't recognize the option passed to the .nan
5653 // directive (e.g. no option or unknown option), emit an error.
5654 reportParseError("invalid option in .nan directive");
5655 return false;
5656}
5657
Jack Carter0b744b32012-10-04 02:29:46 +00005658bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005659 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005660 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005661 const AsmToken &Tok = Parser.getTok();
5662
5663 if (Tok.getString() == "noat") {
5664 return parseSetNoAtDirective();
5665 } else if (Tok.getString() == "at") {
5666 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005667 } else if (Tok.getString() == "arch") {
5668 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005669 } else if (Tok.getString() == "fp") {
5670 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005671 } else if (Tok.getString() == "oddspreg") {
5672 return parseSetOddSPRegDirective();
5673 } else if (Tok.getString() == "nooddspreg") {
5674 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005675 } else if (Tok.getString() == "pop") {
5676 return parseSetPopDirective();
5677 } else if (Tok.getString() == "push") {
5678 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005679 } else if (Tok.getString() == "reorder") {
5680 return parseSetReorderDirective();
5681 } else if (Tok.getString() == "noreorder") {
5682 return parseSetNoReorderDirective();
5683 } else if (Tok.getString() == "macro") {
5684 return parseSetMacroDirective();
5685 } else if (Tok.getString() == "nomacro") {
5686 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005687 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005688 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005689 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005690 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005691 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00005692 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005693 getTargetStreamer().emitDirectiveSetNoMicroMips();
5694 Parser.eatToEndOfStatement();
5695 return false;
5696 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005697 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005698 } else if (Tok.getString() == "mips0") {
5699 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005700 } else if (Tok.getString() == "mips1") {
5701 return parseSetFeature(Mips::FeatureMips1);
5702 } else if (Tok.getString() == "mips2") {
5703 return parseSetFeature(Mips::FeatureMips2);
5704 } else if (Tok.getString() == "mips3") {
5705 return parseSetFeature(Mips::FeatureMips3);
5706 } else if (Tok.getString() == "mips4") {
5707 return parseSetFeature(Mips::FeatureMips4);
5708 } else if (Tok.getString() == "mips5") {
5709 return parseSetFeature(Mips::FeatureMips5);
5710 } else if (Tok.getString() == "mips32") {
5711 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005712 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005713 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005714 } else if (Tok.getString() == "mips32r3") {
5715 return parseSetFeature(Mips::FeatureMips32r3);
5716 } else if (Tok.getString() == "mips32r5") {
5717 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005718 } else if (Tok.getString() == "mips32r6") {
5719 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005720 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005721 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005722 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005723 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005724 } else if (Tok.getString() == "mips64r3") {
5725 return parseSetFeature(Mips::FeatureMips64r3);
5726 } else if (Tok.getString() == "mips64r5") {
5727 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005728 } else if (Tok.getString() == "mips64r6") {
5729 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005730 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005731 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005732 } else if (Tok.getString() == "nodsp") {
5733 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005734 } else if (Tok.getString() == "msa") {
5735 return parseSetMsaDirective();
5736 } else if (Tok.getString() == "nomsa") {
5737 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005738 } else if (Tok.getString() == "softfloat") {
5739 return parseSetSoftFloatDirective();
5740 } else if (Tok.getString() == "hardfloat") {
5741 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005742 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005743 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005744 parseSetAssignment();
5745 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005746 }
Jack Carter07c818d2013-01-25 01:31:34 +00005747
Jack Carter0b744b32012-10-04 02:29:46 +00005748 return true;
5749}
5750
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005751/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005752/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005753bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005754 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005755 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5756 for (;;) {
5757 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005758 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005759 return true;
5760
5761 getParser().getStreamer().EmitValue(Value, Size);
5762
5763 if (getLexer().is(AsmToken::EndOfStatement))
5764 break;
5765
Jack Carter07c818d2013-01-25 01:31:34 +00005766 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005767 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005768 Parser.Lex();
5769 }
5770 }
5771
5772 Parser.Lex();
5773 return false;
5774}
5775
Vladimir Medic4c299852013-11-06 11:27:05 +00005776/// parseDirectiveGpWord
5777/// ::= .gpword local_sym
5778bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005779 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005780 const MCExpr *Value;
5781 // EmitGPRel32Value requires an expression, so we are using base class
5782 // method to evaluate the expression.
5783 if (getParser().parseExpression(Value))
5784 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005785 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005786
Vladimir Medice10c1122013-11-13 13:18:04 +00005787 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005788 return Error(getLexer().getLoc(),
5789 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005790 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005791 return false;
5792}
5793
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005794/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005795/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005796bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005797 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005798 const MCExpr *Value;
5799 // EmitGPRel64Value requires an expression, so we are using base class
5800 // method to evaluate the expression.
5801 if (getParser().parseExpression(Value))
5802 return true;
5803 getParser().getStreamer().EmitGPRel64Value(Value);
5804
5805 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005806 return Error(getLexer().getLoc(),
5807 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005808 Parser.Lex(); // Eat EndOfStatement token.
5809 return false;
5810}
5811
Jack Carter0cd3c192014-01-06 23:27:31 +00005812bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005813 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005814 // Get the option token.
5815 AsmToken Tok = Parser.getTok();
5816 // At the moment only identifiers are supported.
5817 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005818 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005819 Parser.eatToEndOfStatement();
5820 return false;
5821 }
5822
5823 StringRef Option = Tok.getIdentifier();
5824
5825 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005826 // MipsAsmParser needs to know if the current PIC mode changes.
5827 IsPicEnabled = false;
5828
Jack Carter0cd3c192014-01-06 23:27:31 +00005829 getTargetStreamer().emitDirectiveOptionPic0();
5830 Parser.Lex();
5831 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5832 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005833 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005834 Parser.eatToEndOfStatement();
5835 }
5836 return false;
5837 }
5838
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005839 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005840 // MipsAsmParser needs to know if the current PIC mode changes.
5841 IsPicEnabled = true;
5842
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005843 getTargetStreamer().emitDirectiveOptionPic2();
5844 Parser.Lex();
5845 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5846 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005847 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005848 Parser.eatToEndOfStatement();
5849 }
5850 return false;
5851 }
5852
Jack Carter0cd3c192014-01-06 23:27:31 +00005853 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005854 Warning(Parser.getTok().getLoc(),
5855 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005856 Parser.eatToEndOfStatement();
5857 return false;
5858}
5859
Toma Tabacu9ca50962015-04-16 09:53:47 +00005860/// parseInsnDirective
5861/// ::= .insn
5862bool MipsAsmParser::parseInsnDirective() {
5863 // If this is not the end of the statement, report an error.
5864 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5865 reportParseError("unexpected token, expected end of statement");
5866 return false;
5867 }
5868
5869 // The actual label marking happens in
5870 // MipsELFStreamer::createPendingLabelRelocs().
5871 getTargetStreamer().emitDirectiveInsn();
5872
5873 getParser().Lex(); // Eat EndOfStatement token.
5874 return false;
5875}
5876
Simon Atanasyanbe186202016-02-11 06:45:54 +00005877/// parseSSectionDirective
5878/// ::= .sbss
5879/// ::= .sdata
5880bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5881 // If this is not the end of the statement, report an error.
5882 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5883 reportParseError("unexpected token, expected end of statement");
5884 return false;
5885 }
5886
5887 MCSection *ELFSection = getContext().getELFSection(
5888 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5889 getParser().getStreamer().SwitchSection(ELFSection);
5890
5891 getParser().Lex(); // Eat EndOfStatement token.
5892 return false;
5893}
5894
Daniel Sanders7e527422014-07-10 13:38:23 +00005895/// parseDirectiveModule
5896/// ::= .module oddspreg
5897/// ::= .module nooddspreg
5898/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005899/// ::= .module softfloat
5900/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005901bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005902 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005903 MCAsmLexer &Lexer = getLexer();
5904 SMLoc L = Lexer.getLoc();
5905
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005906 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005907 // TODO : get a better message.
5908 reportParseError(".module directive must appear before any code");
5909 return false;
5910 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005911
Toma Tabacuc405c822015-01-23 10:40:19 +00005912 StringRef Option;
5913 if (Parser.parseIdentifier(Option)) {
5914 reportParseError("expected .module option identifier");
5915 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005916 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005917
Toma Tabacuc405c822015-01-23 10:40:19 +00005918 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005919 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005920
Toma Tabacu3c499582015-06-25 10:56:57 +00005921 // Synchronize the abiflags information with the FeatureBits information we
5922 // changed above.
5923 getTargetStreamer().updateABIInfo(*this);
5924
5925 // If printing assembly, use the recently updated abiflags information.
5926 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5927 // emitted at the end).
5928 getTargetStreamer().emitDirectiveModuleOddSPReg();
5929
Toma Tabacuc405c822015-01-23 10:40:19 +00005930 // If this is not the end of the statement, report an error.
5931 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5932 reportParseError("unexpected token, expected end of statement");
5933 return false;
5934 }
5935
5936 return false; // parseDirectiveModule has finished successfully.
5937 } else if (Option == "nooddspreg") {
5938 if (!isABI_O32()) {
5939 Error(L, "'.module nooddspreg' requires the O32 ABI");
5940 return false;
5941 }
5942
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005943 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005944
Toma Tabacu3c499582015-06-25 10:56:57 +00005945 // Synchronize the abiflags information with the FeatureBits information we
5946 // changed above.
5947 getTargetStreamer().updateABIInfo(*this);
5948
5949 // If printing assembly, use the recently updated abiflags information.
5950 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5951 // emitted at the end).
5952 getTargetStreamer().emitDirectiveModuleOddSPReg();
5953
Toma Tabacuc405c822015-01-23 10:40:19 +00005954 // If this is not the end of the statement, report an error.
5955 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5956 reportParseError("unexpected token, expected end of statement");
5957 return false;
5958 }
5959
5960 return false; // parseDirectiveModule has finished successfully.
5961 } else if (Option == "fp") {
5962 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005963 } else if (Option == "softfloat") {
5964 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5965
5966 // Synchronize the ABI Flags information with the FeatureBits information we
5967 // updated above.
5968 getTargetStreamer().updateABIInfo(*this);
5969
5970 // If printing assembly, use the recently updated ABI Flags information.
5971 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5972 // emitted later).
5973 getTargetStreamer().emitDirectiveModuleSoftFloat();
5974
5975 // If this is not the end of the statement, report an error.
5976 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5977 reportParseError("unexpected token, expected end of statement");
5978 return false;
5979 }
5980
5981 return false; // parseDirectiveModule has finished successfully.
5982 } else if (Option == "hardfloat") {
5983 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5984
5985 // Synchronize the ABI Flags information with the FeatureBits information we
5986 // updated above.
5987 getTargetStreamer().updateABIInfo(*this);
5988
5989 // If printing assembly, use the recently updated ABI Flags information.
5990 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5991 // emitted later).
5992 getTargetStreamer().emitDirectiveModuleHardFloat();
5993
5994 // If this is not the end of the statement, report an error.
5995 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5996 reportParseError("unexpected token, expected end of statement");
5997 return false;
5998 }
5999
6000 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00006001 } else {
6002 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
6003 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006004}
6005
6006/// parseDirectiveModuleFP
6007/// ::= =32
6008/// ::= =xx
6009/// ::= =64
6010bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006011 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006012 MCAsmLexer &Lexer = getLexer();
6013
6014 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006015 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006016 return false;
6017 }
6018 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006019
Daniel Sanders7e527422014-07-10 13:38:23 +00006020 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006021 if (!parseFpABIValue(FpABI, ".module"))
6022 return false;
6023
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006024 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006025 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006026 return false;
6027 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006028
Toma Tabacua64e5402015-06-25 12:44:38 +00006029 // Synchronize the abiflags information with the FeatureBits information we
6030 // changed above.
6031 getTargetStreamer().updateABIInfo(*this);
6032
6033 // If printing assembly, use the recently updated abiflags information.
6034 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6035 // emitted at the end).
6036 getTargetStreamer().emitDirectiveModuleFP();
6037
Daniel Sanders7e527422014-07-10 13:38:23 +00006038 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006039 return false;
6040}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006041
Daniel Sanders7e527422014-07-10 13:38:23 +00006042bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006043 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006044 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006045 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006046 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006047
6048 if (Lexer.is(AsmToken::Identifier)) {
6049 StringRef Value = Parser.getTok().getString();
6050 Parser.Lex();
6051
6052 if (Value != "xx") {
6053 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6054 return false;
6055 }
6056
6057 if (!isABI_O32()) {
6058 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
6059 return false;
6060 }
6061
Daniel Sanders7e527422014-07-10 13:38:23 +00006062 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006063 if (ModuleLevelOptions) {
6064 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6065 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6066 } else {
6067 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6068 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6069 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006070 return true;
6071 }
6072
6073 if (Lexer.is(AsmToken::Integer)) {
6074 unsigned Value = Parser.getTok().getIntVal();
6075 Parser.Lex();
6076
6077 if (Value != 32 && Value != 64) {
6078 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6079 return false;
6080 }
6081
6082 if (Value == 32) {
6083 if (!isABI_O32()) {
6084 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6085 return false;
6086 }
6087
Daniel Sanders7e527422014-07-10 13:38:23 +00006088 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006089 if (ModuleLevelOptions) {
6090 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6091 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6092 } else {
6093 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6094 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6095 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006096 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006097 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006098 if (ModuleLevelOptions) {
6099 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6100 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6101 } else {
6102 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6103 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6104 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006105 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006106
Daniel Sanders7e527422014-07-10 13:38:23 +00006107 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006108 }
6109
6110 return false;
6111}
6112
Jack Carter0b744b32012-10-04 02:29:46 +00006113bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006114 // This returns false if this function recognizes the directive
6115 // regardless of whether it is successfully handles or reports an
6116 // error. Otherwise it returns true to give the generic parser a
6117 // chance at recognizing it.
6118
Rafael Espindola961d4692014-11-11 05:18:41 +00006119 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006120 StringRef IDVal = DirectiveID.getString();
6121
Nirav Dave996fc132016-05-05 14:15:46 +00006122 if (IDVal == ".cpload") {
6123 parseDirectiveCpLoad(DirectiveID.getLoc());
6124 return false;
6125 }
6126 if (IDVal == ".cprestore") {
6127 parseDirectiveCpRestore(DirectiveID.getLoc());
6128 return false;
6129 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006130 if (IDVal == ".dword") {
6131 parseDataDirective(8, DirectiveID.getLoc());
6132 return false;
6133 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006134 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006135 StringRef SymbolName;
6136
6137 if (Parser.parseIdentifier(SymbolName)) {
6138 reportParseError("expected identifier after .ent");
6139 return false;
6140 }
6141
6142 // There's an undocumented extension that allows an integer to
6143 // follow the name of the procedure which AFAICS is ignored by GAS.
6144 // Example: .ent foo,2
6145 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6146 if (getLexer().isNot(AsmToken::Comma)) {
6147 // Even though we accept this undocumented extension for compatibility
6148 // reasons, the additional integer argument does not actually change
6149 // the behaviour of the '.ent' directive, so we would like to discourage
6150 // its use. We do this by not referring to the extended version in
6151 // error messages which are not directly related to its use.
6152 reportParseError("unexpected token, expected end of statement");
6153 return false;
6154 }
6155 Parser.Lex(); // Eat the comma.
6156 const MCExpr *DummyNumber;
6157 int64_t DummyNumberVal;
6158 // If the user was explicitly trying to use the extended version,
6159 // we still give helpful extension-related error messages.
6160 if (Parser.parseExpression(DummyNumber)) {
6161 reportParseError("expected number after comma");
6162 return false;
6163 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006164 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006165 reportParseError("expected an absolute expression after comma");
6166 return false;
6167 }
6168 }
6169
6170 // If this is not the end of the statement, report an error.
6171 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6172 reportParseError("unexpected token, expected end of statement");
6173 return false;
6174 }
6175
Jim Grosbach6f482002015-05-18 18:43:14 +00006176 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006177
6178 getTargetStreamer().emitDirectiveEnt(*Sym);
6179 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006180 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006181 return false;
6182 }
6183
Jack Carter07c818d2013-01-25 01:31:34 +00006184 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006185 StringRef SymbolName;
6186
6187 if (Parser.parseIdentifier(SymbolName)) {
6188 reportParseError("expected identifier after .end");
6189 return false;
6190 }
6191
6192 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6193 reportParseError("unexpected token, expected end of statement");
6194 return false;
6195 }
6196
6197 if (CurrentFn == nullptr) {
6198 reportParseError(".end used without .ent");
6199 return false;
6200 }
6201
6202 if ((SymbolName != CurrentFn->getName())) {
6203 reportParseError(".end symbol does not match .ent symbol");
6204 return false;
6205 }
6206
6207 getTargetStreamer().emitDirectiveEnd(SymbolName);
6208 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006209 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006210 return false;
6211 }
6212
Jack Carter07c818d2013-01-25 01:31:34 +00006213 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006214 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6215 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006216 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006217 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6218 reportParseError("expected stack register");
6219 return false;
6220 }
6221
6222 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6223 if (!StackRegOpnd.isGPRAsmReg()) {
6224 reportParseError(StackRegOpnd.getStartLoc(),
6225 "expected general purpose register");
6226 return false;
6227 }
6228 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6229
6230 if (Parser.getTok().is(AsmToken::Comma))
6231 Parser.Lex();
6232 else {
6233 reportParseError("unexpected token, expected comma");
6234 return false;
6235 }
6236
6237 // Parse the frame size.
6238 const MCExpr *FrameSize;
6239 int64_t FrameSizeVal;
6240
6241 if (Parser.parseExpression(FrameSize)) {
6242 reportParseError("expected frame size value");
6243 return false;
6244 }
6245
Jim Grosbach13760bd2015-05-30 01:25:56 +00006246 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006247 reportParseError("frame size 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 return register.
6259 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006260 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006261 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6262 reportParseError("expected return register");
6263 return false;
6264 }
6265
6266 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6267 if (!ReturnRegOpnd.isGPRAsmReg()) {
6268 reportParseError(ReturnRegOpnd.getStartLoc(),
6269 "expected general purpose register");
6270 return false;
6271 }
6272
6273 // If this is not the end of the statement, report an error.
6274 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6275 reportParseError("unexpected token, expected end of statement");
6276 return false;
6277 }
6278
6279 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6280 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006281 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006282 return false;
6283 }
6284
Jack Carter07c818d2013-01-25 01:31:34 +00006285 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006286 parseDirectiveSet();
6287 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006288 }
6289
Daniel Sandersd97a6342014-08-13 10:07:34 +00006290 if (IDVal == ".mask" || IDVal == ".fmask") {
6291 // .mask bitmask, frame_offset
6292 // bitmask: One bit for each register used.
6293 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6294 // first register is expected to be saved.
6295 // Examples:
6296 // .mask 0x80000000, -4
6297 // .fmask 0x80000000, -4
6298 //
Jack Carterbe332172012-09-07 00:48:02 +00006299
Daniel Sandersd97a6342014-08-13 10:07:34 +00006300 // Parse the bitmask
6301 const MCExpr *BitMask;
6302 int64_t BitMaskVal;
6303
6304 if (Parser.parseExpression(BitMask)) {
6305 reportParseError("expected bitmask value");
6306 return false;
6307 }
6308
Jim Grosbach13760bd2015-05-30 01:25:56 +00006309 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006310 reportParseError("bitmask not an absolute expression");
6311 return false;
6312 }
6313
6314 if (Parser.getTok().is(AsmToken::Comma))
6315 Parser.Lex();
6316 else {
6317 reportParseError("unexpected token, expected comma");
6318 return false;
6319 }
6320
6321 // Parse the frame_offset
6322 const MCExpr *FrameOffset;
6323 int64_t FrameOffsetVal;
6324
6325 if (Parser.parseExpression(FrameOffset)) {
6326 reportParseError("expected frame offset value");
6327 return false;
6328 }
6329
Jim Grosbach13760bd2015-05-30 01:25:56 +00006330 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006331 reportParseError("frame offset not an absolute expression");
6332 return false;
6333 }
6334
6335 // If this is not the end of the statement, report an error.
6336 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6337 reportParseError("unexpected token, expected end of statement");
6338 return false;
6339 }
6340
6341 if (IDVal == ".mask")
6342 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6343 else
6344 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006345 return false;
6346 }
6347
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006348 if (IDVal == ".nan")
6349 return parseDirectiveNaN();
6350
Jack Carter07c818d2013-01-25 01:31:34 +00006351 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006352 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006353 return false;
6354 }
6355
Rafael Espindolab59fb732014-03-28 18:50:26 +00006356 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006357 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006358 return false;
6359 }
6360
Jack Carter07c818d2013-01-25 01:31:34 +00006361 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006362 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006363 return false;
6364 }
6365
Scott Egertond1aeb052016-02-15 16:11:51 +00006366 if (IDVal == ".hword") {
6367 parseDataDirective(2, DirectiveID.getLoc());
6368 return false;
6369 }
6370
Nirav Dave996fc132016-05-05 14:15:46 +00006371 if (IDVal == ".option") {
6372 parseDirectiveOption();
6373 return false;
6374 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006375
6376 if (IDVal == ".abicalls") {
6377 getTargetStreamer().emitDirectiveAbiCalls();
6378 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006379 Error(Parser.getTok().getLoc(),
6380 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006381 // Clear line
6382 Parser.eatToEndOfStatement();
6383 }
6384 return false;
6385 }
6386
Nirav Dave996fc132016-05-05 14:15:46 +00006387 if (IDVal == ".cpsetup") {
6388 parseDirectiveCPSetup();
6389 return false;
6390 }
6391 if (IDVal == ".cpreturn") {
6392 parseDirectiveCPReturn();
6393 return false;
6394 }
6395 if (IDVal == ".module") {
6396 parseDirectiveModule();
6397 return false;
6398 }
6399 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6400 parseInternalDirectiveReallowModule();
6401 return false;
6402 }
6403 if (IDVal == ".insn") {
6404 parseInsnDirective();
6405 return false;
6406 }
6407 if (IDVal == ".sbss") {
6408 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6409 return false;
6410 }
6411 if (IDVal == ".sdata") {
6412 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6413 return false;
6414 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006415
Rafael Espindola870c4e92012-01-11 03:56:41 +00006416 return true;
6417}
6418
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006419bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6420 // If this is not the end of the statement, report an error.
6421 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6422 reportParseError("unexpected token, expected end of statement");
6423 return false;
6424 }
6425
6426 getTargetStreamer().reallowModuleDirective();
6427
6428 getParser().Lex(); // Eat EndOfStatement token.
6429 return false;
6430}
6431
Rafael Espindola870c4e92012-01-11 03:56:41 +00006432extern "C" void LLVMInitializeMipsAsmParser() {
6433 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6434 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6435 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6436 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6437}
Jack Carterb4dbc172012-09-05 23:34:03 +00006438
6439#define GET_REGISTER_MATCHER
6440#define GET_MATCHER_IMPLEMENTATION
6441#include "MipsGenAsmMatcher.inc"