blob: 5b1b65f37e55c924f03a73655eb53fd5466a708a [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"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000017#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000022#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000023#include "llvm/MC/MCParser/MCAsmLexer.h"
24#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000025#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000026#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000027#include "llvm/MC/MCStreamer.h"
28#include "llvm/MC/MCSubtargetInfo.h"
29#include "llvm/MC/MCSymbol.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000030#include "llvm/Support/Debug.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000031#include "llvm/Support/ELF.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000032#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000033#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000034#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000035#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000036#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000037
38using namespace llvm;
39
Chandler Carruthe96dd892014-04-21 22:55:11 +000040#define DEBUG_TYPE "mips-asm-parser"
41
Joey Gouly0e76fa72013-09-12 10:28:05 +000042namespace llvm {
43class MCInstrInfo;
44}
45
Rafael Espindola870c4e92012-01-11 03:56:41 +000046namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000047class MipsAssemblerOptions {
48public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000049 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000050 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000051
Toma Tabacu9db22db2014-09-09 10:15:38 +000052 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000053 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000054 Reorder = Opts->isReorder();
55 Macro = Opts->isMacro();
56 Features = Opts->getFeatures();
57 }
58
Toma Tabacub19cf202015-04-27 13:12:59 +000059 unsigned getATRegIndex() const { return ATReg; }
60 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000061 if (Reg > 31)
62 return false;
63
64 ATReg = Reg;
65 return true;
66 }
Jack Carter0b744b32012-10-04 02:29:46 +000067
Toma Tabacu9db22db2014-09-09 10:15:38 +000068 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000069 void setReorder() { Reorder = true; }
70 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000071
Toma Tabacu9db22db2014-09-09 10:15:38 +000072 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000073 void setMacro() { Macro = true; }
74 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000075
Toma Tabacu465acfd2015-06-09 13:33:26 +000076 const FeatureBitset &getFeatures() const { return Features; }
77 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000078
Daniel Sandersf0df2212014-08-04 12:20:00 +000079 // Set of features that are either architecture features or referenced
80 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
81 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
82 // The reason we need this mask is explained in the selectArch function.
83 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000084 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000085
Jack Carter0b744b32012-10-04 02:29:46 +000086private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000087 unsigned ATReg;
88 bool Reorder;
89 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000090 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000091};
92}
93
Michael Kupersteindb0712f2015-05-26 10:47:10 +000094const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
95 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
96 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
97 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
98 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
99 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
100 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
101 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
102 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
103};
104
Jack Carter0b744b32012-10-04 02:29:46 +0000105namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000106class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000107 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000108 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000109 return static_cast<MipsTargetStreamer &>(TS);
110 }
111
Eric Christophera5762812015-01-26 17:33:46 +0000112 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000113 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000114 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
115 // nullptr, which indicates that no function is currently
116 // selected. This usually happens after an '.end func'
117 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000118 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000119 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000120 bool IsCpRestoreSet;
121 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000122 unsigned CpSaveLocation;
123 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
124 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000125
Daniel Sandersef638fe2014-10-03 15:37:37 +0000126 // Print a warning along with its fix-it message at the given range.
127 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
128 SMRange Range, bool ShowColors = true);
129
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000130#define GET_ASSEMBLER_HEADER
131#include "MipsGenAsmMatcher.inc"
132
Matheus Almeida595fcab2014-06-11 15:05:56 +0000133 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
134
Chad Rosier49963552012-10-13 00:26:04 +0000135 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000136 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000137 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000138 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000139
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000140 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000141 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000144
Toma Tabacu13964452014-09-04 13:23:44 +0000145 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000146
David Blaikie960ea3f2014-06-08 16:18:35 +0000147 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
148 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000149
Craig Topper56c590a2014-04-29 07:58:02 +0000150 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000151
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000152 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
153 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000154 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000155 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000156 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
157 SMLoc S);
158 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
159 OperandMatchResultTy parseImm(OperandVector &Operands);
160 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
161 OperandMatchResultTy parseInvNum(OperandVector &Operands);
162 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
163 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
164 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
165 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000166
David Blaikie960ea3f2014-06-08 16:18:35 +0000167 bool searchSymbolAlias(OperandVector &Operands);
168
Toma Tabacu13964452014-09-04 13:23:44 +0000169 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000170
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000171 enum MacroExpanderResultTy {
172 MER_NotAMacro,
173 MER_Success,
174 MER_Fail,
175 };
Jack Carter30a59822012-10-04 04:03:53 +0000176
Matheus Almeida3813d572014-06-19 14:39:14 +0000177 // Expands assembly pseudo instructions.
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000178 MacroExpanderResultTy
179 tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
180 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000181
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000182 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
183 SmallVectorImpl<MCInst> &Instructions);
184
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000185 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000186 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000187 SmallVectorImpl<MCInst> &Instructions);
188
Toma Tabacuf712ede2015-06-17 14:31:51 +0000189 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
190 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
191 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000192
Toma Tabacu00e98672015-05-01 12:19:27 +0000193 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000194 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000195
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000196 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
197 const MCOperand &Offset, bool Is32BitAddress,
198 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000199
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000200 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
201 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000202
Jack Carter9e65aa32013-03-22 00:05:30 +0000203 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000204 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
205 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000206
207 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
208 SmallVectorImpl<MCInst> &Instructions);
209
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000210 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
211 SmallVectorImpl<MCInst> &Instructions);
212
Toma Tabacue1e460d2015-06-11 10:36:10 +0000213 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
214 SmallVectorImpl<MCInst> &Instructions);
215
Toma Tabacu1a108322015-06-17 13:20:24 +0000216 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
217 SmallVectorImpl<MCInst> &Instructions);
218
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000219 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
220 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
221 const bool Signed);
222
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000223 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
224 SmallVectorImpl<MCInst> &Instructions);
225
Daniel Sanders6394ee52015-10-15 14:52:58 +0000226 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
227 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000228
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000229 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
230 SmallVectorImpl<MCInst> &Instructions);
231
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000232 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
233 SmallVectorImpl<MCInst> &Instructions);
234 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc,
235 SmallVectorImpl<MCInst> &Instructions);
236 bool expandDRotation(MCInst &Inst, SMLoc IDLoc,
237 SmallVectorImpl<MCInst> &Instructions);
238 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
239 SmallVectorImpl<MCInst> &Instructions);
240
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000241 bool expandAbs(MCInst &Inst, SMLoc IDLoc,
242 SmallVectorImpl<MCInst> &Instructions);
243
Toma Tabacu234482a2015-03-16 12:03:39 +0000244 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
245 SmallVectorImpl<MCInst> &Instructions);
246
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000247 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000248 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000249
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000250 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
251 SmallVectorImpl<MCInst> &Instructions);
252
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000253 bool reportParseError(Twine ErrorMsg);
254 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000255
Jack Carterb5cf5902013-04-17 00:18:04 +0000256 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000257 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000258
Vladimir Medic4c299852013-11-06 11:27:05 +0000259 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000260
261 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000262 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000263 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000264 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000265 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000266 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000267 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000268 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000269 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000270 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000271 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000272 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000273 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000274 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000275
276 bool parseSetAtDirective();
277 bool parseSetNoAtDirective();
278 bool parseSetMacroDirective();
279 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000280 bool parseSetMsaDirective();
281 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000282 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000283 bool parseSetReorderDirective();
284 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000285 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000286 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000287 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000288 bool parseSetOddSPRegDirective();
289 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000290 bool parseSetPopDirective();
291 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000292 bool parseSetSoftFloatDirective();
293 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000294
Jack Carterd76b2372013-03-21 21:44:16 +0000295 bool parseSetAssignment();
296
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000297 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000298 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000299 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000300 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000301 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000302 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
303 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000304
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000305 bool parseInternalDirectiveReallowModule();
306
Jack Carterdc1e35d2012-09-06 20:00:02 +0000307 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000308
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000309 bool eatComma(StringRef ErrorStr);
310
Jack Carter1ac53222013-02-20 23:11:17 +0000311 int matchCPURegisterName(StringRef Symbol);
312
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000313 int matchHWRegsRegisterName(StringRef Symbol);
314
Jack Carter873c7242013-01-12 01:03:14 +0000315 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000316
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000317 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000318
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000319 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000320
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000321 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000322
Jack Carter5dc8ac92013-09-25 23:50:44 +0000323 int matchMSA128RegisterName(StringRef Name);
324
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000325 int matchMSA128CtrlRegisterName(StringRef Name);
326
Jack Carterd0bd6422013-04-18 00:41:53 +0000327 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000328
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000329 unsigned getGPR(int RegNo);
330
Toma Tabacu89a712b2015-04-15 10:48:56 +0000331 /// Returns the internal register number for the current AT. Also checks if
332 /// the current AT is unavailable (set to $0) and gives an error if it is.
333 /// This should be used in pseudo-instruction expansions which need AT.
334 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000335
336 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000337 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000338
339 // Helper function that checks if the value of a vector index is within the
340 // boundaries of accepted values for each RegisterKind
341 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
342 bool validateMSAIndex(int Val, int RegKind);
343
Daniel Sandersf0df2212014-08-04 12:20:00 +0000344 // Selects a new architecture by updating the FeatureBits with the necessary
345 // info including implied dependencies.
346 // Internally, it clears all the feature bits related to *any* architecture
347 // and selects the new one using the ToggleFeature functionality of the
348 // MCSubtargetInfo object that handles implied dependencies. The reason we
349 // clear all the arch related bits manually is because ToggleFeature only
350 // clears the features that imply the feature being cleared and not the
351 // features implied by the feature being cleared. This is easier to see
352 // with an example:
353 // --------------------------------------------------
354 // | Feature | Implies |
355 // | -------------------------------------------------|
356 // | FeatureMips1 | None |
357 // | FeatureMips2 | FeatureMips1 |
358 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
359 // | FeatureMips4 | FeatureMips3 |
360 // | ... | |
361 // --------------------------------------------------
362 //
363 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
364 // FeatureMipsGP64 | FeatureMips1)
365 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
366 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000367 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000368 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000369 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
370 STI.setFeatureBits(FeatureBits);
371 setAvailableFeatures(
372 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000373 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000374 }
375
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000376 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000377 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000378 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000379 setAvailableFeatures(
380 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000381 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000382 }
383 }
384
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000385 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000386 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000387 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000388 setAvailableFeatures(
389 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000390 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000391 }
392 }
393
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000394 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
395 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000396 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000397 }
398
399 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
400 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000401 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000402 }
403
Rafael Espindola870c4e92012-01-11 03:56:41 +0000404public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000405 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000406 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000407#define GET_OPERAND_DIAGNOSTIC_TYPES
408#include "MipsGenAsmMatcher.inc"
409#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000410 };
411
Akira Hatanakab11ef082015-11-14 06:35:56 +0000412 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000413 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000414 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000415 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
416 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000417 MCAsmParserExtension::Initialize(parser);
418
Toma Tabacu11e14a92015-04-21 11:50:52 +0000419 parser.addAliasForDirective(".asciiz", ".asciz");
420
Jack Carterb4dbc172012-09-05 23:34:03 +0000421 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000422 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000423
Toma Tabacu9db22db2014-09-09 10:15:38 +0000424 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000425 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000426 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000427
Toma Tabacu9db22db2014-09-09 10:15:38 +0000428 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000429 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000430 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000431
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000432 getTargetStreamer().updateABIInfo(*this);
433
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000434 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000435 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000436
437 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000438
Daniel Sandersa6994442015-08-18 12:33:54 +0000439 IsPicEnabled =
440 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
441
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000442 IsCpRestoreSet = false;
443 CpRestoreOffset = -1;
444
Daniel Sanders50f17232015-09-15 16:17:27 +0000445 Triple TheTriple(sti.getTargetTriple());
446 if ((TheTriple.getArch() == Triple::mips) ||
447 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000448 IsLittleEndian = false;
449 else
450 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000451 }
452
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000453 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
454 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
455
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000456 bool isGP64bit() const {
457 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
458 }
459 bool isFP64bit() const {
460 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
461 }
Eric Christophera5762812015-01-26 17:33:46 +0000462 const MipsABIInfo &getABI() const { return ABI; }
463 bool isABI_N32() const { return ABI.IsN32(); }
464 bool isABI_N64() const { return ABI.IsN64(); }
465 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000466 bool isABI_FPXX() const {
467 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
468 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000469
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000470 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000471 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000472 }
473
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000474 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000475 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000476 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000477 bool hasMips1() const {
478 return getSTI().getFeatureBits()[Mips::FeatureMips1];
479 }
480 bool hasMips2() const {
481 return getSTI().getFeatureBits()[Mips::FeatureMips2];
482 }
483 bool hasMips3() const {
484 return getSTI().getFeatureBits()[Mips::FeatureMips3];
485 }
486 bool hasMips4() const {
487 return getSTI().getFeatureBits()[Mips::FeatureMips4];
488 }
489 bool hasMips5() const {
490 return getSTI().getFeatureBits()[Mips::FeatureMips5];
491 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000492 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000493 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000494 }
495 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000496 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 }
498 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000500 }
501 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000502 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000503 }
Daniel Sanders17793142015-02-18 16:24:50 +0000504 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000505 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000506 }
507 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000508 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000509 }
510 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000511 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000512 }
513 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000514 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000515 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000516 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000517 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000518 }
519 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000520 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000521 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000522
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000523 bool hasDSP() const {
524 return getSTI().getFeatureBits()[Mips::FeatureDSP];
525 }
526 bool hasDSPR2() const {
527 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
528 }
529 bool hasDSPR3() const {
530 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
531 }
532 bool hasMSA() const {
533 return getSTI().getFeatureBits()[Mips::FeatureMSA];
534 }
Kai Nackee0245392015-01-27 19:11:28 +0000535 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000536 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000537 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000538
Daniel Sandersa6994442015-08-18 12:33:54 +0000539 bool inPicMode() {
540 return IsPicEnabled;
541 }
542
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000543 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000545 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000546
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000547 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000548 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000549 }
550
Eric Christophere8ae3e32015-05-07 23:10:21 +0000551 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000552 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000553 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000554
Toma Tabacud9d344b2015-04-27 14:05:04 +0000555 /// Warn if RegIndex is the same as the current AT.
556 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000557
558 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000559
560 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000561};
562}
563
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000564namespace {
565
566/// MipsOperand - Instances of this class represent a parsed Mips machine
567/// instruction.
568class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000569public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000570 /// Broad categories of register classes
571 /// The exact class is finalized by the render method.
572 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000573 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000574 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000575 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000576 RegKind_FCC = 4, /// FCC
577 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
578 RegKind_MSACtrl = 16, /// MSA control registers
579 RegKind_COP2 = 32, /// COP2
580 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
581 /// context).
582 RegKind_CCR = 128, /// CCR
583 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000584 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000585 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000586 /// Potentially any (e.g. $1)
587 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
588 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000589 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000590 };
591
592private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000593 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000594 k_Immediate, /// An immediate (possibly involving symbol references)
595 k_Memory, /// Base + Offset Memory Address
596 k_PhysRegister, /// A physical register from the Mips namespace
597 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000598 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000599 k_RegList, /// A physical register list
600 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000601 } Kind;
602
David Blaikie960ea3f2014-06-08 16:18:35 +0000603public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000604 MipsOperand(KindTy K, MipsAsmParser &Parser)
605 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
606
David Blaikie960ea3f2014-06-08 16:18:35 +0000607private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000608 /// For diagnostics, and checking the assembler temporary
609 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000610
Eric Christopher8996c5d2013-03-15 00:42:55 +0000611 struct Token {
612 const char *Data;
613 unsigned Length;
614 };
615
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000616 struct PhysRegOp {
617 unsigned Num; /// Register Number
618 };
619
620 struct RegIdxOp {
621 unsigned Index; /// Index into the register class
622 RegKind Kind; /// Bitfield of the kinds it could possibly be
623 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000624 };
625
626 struct ImmOp {
627 const MCExpr *Val;
628 };
629
630 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000631 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000632 const MCExpr *Off;
633 };
634
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000635 struct RegListOp {
636 SmallVector<unsigned, 10> *List;
637 };
638
Jack Carterb4dbc172012-09-05 23:34:03 +0000639 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000640 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000641 struct PhysRegOp PhysReg;
642 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000643 struct ImmOp Imm;
644 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000645 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000646 };
647
648 SMLoc StartLoc, EndLoc;
649
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000650 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000651 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
652 const MCRegisterInfo *RegInfo,
653 SMLoc S, SMLoc E,
654 MipsAsmParser &Parser) {
655 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000656 Op->RegIdx.Index = Index;
657 Op->RegIdx.RegInfo = RegInfo;
658 Op->RegIdx.Kind = RegKind;
659 Op->StartLoc = S;
660 Op->EndLoc = E;
661 return Op;
662 }
663
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000664public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000665 /// Coerce the register to GPR32 and return the real register for the current
666 /// target.
667 unsigned getGPR32Reg() const {
668 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000669 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000670 unsigned ClassID = Mips::GPR32RegClassID;
671 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000672 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000673
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000674 /// Coerce the register to GPR32 and return the real register for the current
675 /// target.
676 unsigned getGPRMM16Reg() const {
677 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
678 unsigned ClassID = Mips::GPR32RegClassID;
679 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
680 }
681
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000682 /// Coerce the register to GPR64 and return the real register for the current
683 /// target.
684 unsigned getGPR64Reg() const {
685 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
686 unsigned ClassID = Mips::GPR64RegClassID;
687 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000688 }
689
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000690private:
691 /// Coerce the register to AFGR64 and return the real register for the current
692 /// target.
693 unsigned getAFGR64Reg() const {
694 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
695 if (RegIdx.Index % 2 != 0)
696 AsmParser.Warning(StartLoc, "Float register should be even.");
697 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
698 .getRegister(RegIdx.Index / 2);
699 }
700
701 /// Coerce the register to FGR64 and return the real register for the current
702 /// target.
703 unsigned getFGR64Reg() const {
704 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
705 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
706 .getRegister(RegIdx.Index);
707 }
708
709 /// Coerce the register to FGR32 and return the real register for the current
710 /// target.
711 unsigned getFGR32Reg() const {
712 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
713 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
714 .getRegister(RegIdx.Index);
715 }
716
717 /// Coerce the register to FGRH32 and return the real register for the current
718 /// target.
719 unsigned getFGRH32Reg() const {
720 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
721 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
722 .getRegister(RegIdx.Index);
723 }
724
725 /// Coerce the register to FCC and return the real register for the current
726 /// target.
727 unsigned getFCCReg() const {
728 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
729 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
730 .getRegister(RegIdx.Index);
731 }
732
733 /// Coerce the register to MSA128 and return the real register for the current
734 /// target.
735 unsigned getMSA128Reg() const {
736 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
737 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
738 // identical
739 unsigned ClassID = Mips::MSA128BRegClassID;
740 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
741 }
742
743 /// Coerce the register to MSACtrl and return the real register for the
744 /// current target.
745 unsigned getMSACtrlReg() const {
746 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
747 unsigned ClassID = Mips::MSACtrlRegClassID;
748 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
749 }
750
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000751 /// Coerce the register to COP0 and return the real register for the
752 /// current target.
753 unsigned getCOP0Reg() const {
754 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
755 unsigned ClassID = Mips::COP0RegClassID;
756 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
757 }
758
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000759 /// Coerce the register to COP2 and return the real register for the
760 /// current target.
761 unsigned getCOP2Reg() const {
762 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
763 unsigned ClassID = Mips::COP2RegClassID;
764 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
765 }
766
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000767 /// Coerce the register to COP3 and return the real register for the
768 /// current target.
769 unsigned getCOP3Reg() const {
770 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
771 unsigned ClassID = Mips::COP3RegClassID;
772 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
773 }
774
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000775 /// Coerce the register to ACC64DSP and return the real register for the
776 /// current target.
777 unsigned getACC64DSPReg() const {
778 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
779 unsigned ClassID = Mips::ACC64DSPRegClassID;
780 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
781 }
782
783 /// Coerce the register to HI32DSP and return the real register for the
784 /// current target.
785 unsigned getHI32DSPReg() const {
786 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
787 unsigned ClassID = Mips::HI32DSPRegClassID;
788 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
789 }
790
791 /// Coerce the register to LO32DSP and return the real register for the
792 /// current target.
793 unsigned getLO32DSPReg() const {
794 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
795 unsigned ClassID = Mips::LO32DSPRegClassID;
796 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
797 }
798
799 /// Coerce the register to CCR and return the real register for the
800 /// current target.
801 unsigned getCCRReg() const {
802 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
803 unsigned ClassID = Mips::CCRRegClassID;
804 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
805 }
806
807 /// Coerce the register to HWRegs and return the real register for the
808 /// current target.
809 unsigned getHWRegsReg() const {
810 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
811 unsigned ClassID = Mips::HWRegsRegClassID;
812 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
813 }
814
815public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000816 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000817 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000818 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000819 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000820 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000821 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000822 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000823 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000824 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000825
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000826 void addRegOperands(MCInst &Inst, unsigned N) const {
827 llvm_unreachable("Use a custom parser instead");
828 }
829
Daniel Sanders21bce302014-04-01 12:35:23 +0000830 /// Render the operand to an MCInst as a GPR32
831 /// Asserts if the wrong number of operands are requested, or the operand
832 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000833 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
834 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000835 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836 }
837
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000838 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
839 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000840 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000841 }
842
Jozef Kolek1904fa22014-11-24 14:25:53 +0000843 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
844 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000845 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000846 }
847
Zoran Jovanovic41688672015-02-10 16:36:20 +0000848 void addGPRMM16AsmRegMovePOperands(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(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000851 }
852
Daniel Sanders21bce302014-04-01 12:35:23 +0000853 /// Render the operand to an MCInst as a GPR64
854 /// Asserts if the wrong number of operands are requested, or the operand
855 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000856 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
857 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000858 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000859 }
860
861 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
862 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000863 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000864 }
865
866 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
867 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000868 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000869 }
870
871 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
872 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000873 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000874 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000875 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000876 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
877 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000878 }
879
880 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
881 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000882 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000883 }
884
885 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
886 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000887 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000888 }
889
890 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
891 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000892 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000893 }
894
895 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
896 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000897 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000898 }
899
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000900 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
901 assert(N == 1 && "Invalid number of operands!");
902 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
903 }
904
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000905 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
906 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000907 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000908 }
909
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000910 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
911 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000912 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000913 }
914
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000915 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
916 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000917 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000918 }
919
920 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
921 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000922 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000923 }
924
925 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
926 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000927 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000928 }
929
930 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
931 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000932 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000933 }
934
935 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
936 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000937 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000938 }
939
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000940 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000941 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
942 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000943 uint64_t Imm = getConstantImm() - Offset;
944 Imm &= (1 << Bits) - 1;
945 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000946 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000947 Inst.addOperand(MCOperand::createImm(Imm));
948 }
949
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000950 template <unsigned Bits>
951 void addUImmOperands(MCInst &Inst, unsigned N) const {
952 if (isImm() && !isConstantImm()) {
953 addExpr(Inst, getImm());
954 return;
955 }
956 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
957 }
958
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000959 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000960 assert(N == 1 && "Invalid number of operands!");
961 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000962 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000963 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000964
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000965 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000966 assert(N == 2 && "Invalid number of operands!");
967
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000968 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
969 ? getMemBase()->getGPR64Reg()
970 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000971
972 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000973 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000974 }
975
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000976 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
977 assert(N == 2 && "Invalid number of operands!");
978
Jim Grosbache9119e42015-05-13 18:37:00 +0000979 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000980
981 const MCExpr *Expr = getMemOff();
982 addExpr(Inst, Expr);
983 }
984
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000985 void addRegListOperands(MCInst &Inst, unsigned N) const {
986 assert(N == 1 && "Invalid number of operands!");
987
988 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000989 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000990 }
991
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000992 void addRegPairOperands(MCInst &Inst, unsigned N) const {
993 assert(N == 2 && "Invalid number of operands!");
994 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000995 Inst.addOperand(MCOperand::createReg(RegNo++));
996 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000997 }
998
Zoran Jovanovic41688672015-02-10 16:36:20 +0000999 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1000 assert(N == 2 && "Invalid number of operands!");
1001 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001002 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001003 }
1004
Craig Topper56c590a2014-04-29 07:58:02 +00001005 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001006 // As a special case until we sort out the definition of div/divu, pretend
1007 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1008 if (isGPRAsmReg() && RegIdx.Index == 0)
1009 return true;
1010
1011 return Kind == k_PhysRegister;
1012 }
1013 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001014 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001015 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +00001016 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001017 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001018 bool isConstantImmz() const {
1019 return isConstantImm() && getConstantImm() == 0;
1020 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001021 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1022 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1023 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001024 template <unsigned Bits> bool isUImm() const {
1025 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1026 }
1027 template <unsigned Bits> bool isAnyImm() const {
1028 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1029 isUInt<Bits>(getConstantImm()))
1030 : isImm();
1031 }
Zlatko Buljan252cca52015-12-18 08:59:37 +00001032 template <unsigned Bits> bool isConstantSImm() const {
1033 return isConstantImm() && isInt<Bits>(getConstantImm());
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001034 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001035 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1036 return isConstantImm() && getConstantImm() >= Bottom &&
1037 getConstantImm() <= Top;
1038 }
Craig Topper56c590a2014-04-29 07:58:02 +00001039 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001040 // Note: It's not possible to pretend that other operand kinds are tokens.
1041 // The matcher emitter checks tokens first.
1042 return Kind == k_Token;
1043 }
Craig Topper56c590a2014-04-29 07:58:02 +00001044 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001045 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001046 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001047 }
1048 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001049 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1050 && getMemBase()->isGPRAsmReg();
1051 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001052 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
1053 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
1054 getMemBase()->isGPRAsmReg();
1055 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001056 bool isMemWithGRPMM16Base() const {
1057 return isMem() && getMemBase()->isMM16AsmReg();
1058 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001059 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1060 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1061 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1062 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001063 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1064 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1065 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1066 && (getMemBase()->getGPR32Reg() == Mips::SP);
1067 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001068 template <unsigned Bits, unsigned ShiftLeftAmount>
1069 bool isScaledUImm() const {
1070 return isConstantImm() &&
1071 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001072 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001073 bool isRegList16() const {
1074 if (!isRegList())
1075 return false;
1076
1077 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001078 if (Size < 2 || Size > 5)
1079 return false;
1080
1081 unsigned R0 = RegList.List->front();
1082 unsigned R1 = RegList.List->back();
1083 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1084 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001085 return false;
1086
1087 int PrevReg = *RegList.List->begin();
1088 for (int i = 1; i < Size - 1; i++) {
1089 int Reg = (*(RegList.List))[i];
1090 if ( Reg != PrevReg + 1)
1091 return false;
1092 PrevReg = Reg;
1093 }
1094
1095 return true;
1096 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001097 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001098 bool isLSAImm() const {
1099 if (!isConstantImm())
1100 return false;
1101 int64_t Val = getConstantImm();
1102 return 1 <= Val && Val <= 4;
1103 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001104 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001105 bool isMovePRegPair() const {
1106 if (Kind != k_RegList || RegList.List->size() != 2)
1107 return false;
1108
1109 unsigned R0 = RegList.List->front();
1110 unsigned R1 = RegList.List->back();
1111
1112 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1113 (R0 == Mips::A1 && R1 == Mips::A3) ||
1114 (R0 == Mips::A2 && R1 == Mips::A3) ||
1115 (R0 == Mips::A0 && R1 == Mips::S5) ||
1116 (R0 == Mips::A0 && R1 == Mips::S6) ||
1117 (R0 == Mips::A0 && R1 == Mips::A1) ||
1118 (R0 == Mips::A0 && R1 == Mips::A2) ||
1119 (R0 == Mips::A0 && R1 == Mips::A3))
1120 return true;
1121
1122 return false;
1123 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001124
1125 StringRef getToken() const {
1126 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001127 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001128 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001129 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001130
Craig Topper56c590a2014-04-29 07:58:02 +00001131 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001132 // As a special case until we sort out the definition of div/divu, pretend
1133 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1134 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1135 RegIdx.Kind & RegKind_GPR)
1136 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001137
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001138 assert(Kind == k_PhysRegister && "Invalid access!");
1139 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001140 }
1141
Jack Carterb4dbc172012-09-05 23:34:03 +00001142 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001143 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001144 return Imm.Val;
1145 }
1146
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001147 int64_t getConstantImm() const {
1148 const MCExpr *Val = getImm();
1149 return static_cast<const MCConstantExpr *>(Val)->getValue();
1150 }
1151
1152 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001153 assert((Kind == k_Memory) && "Invalid access!");
1154 return Mem.Base;
1155 }
1156
1157 const MCExpr *getMemOff() const {
1158 assert((Kind == k_Memory) && "Invalid access!");
1159 return Mem.Off;
1160 }
1161
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001162 int64_t getConstantMemOff() const {
1163 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1164 }
1165
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001166 const SmallVectorImpl<unsigned> &getRegList() const {
1167 assert((Kind == k_RegList) && "Invalid access!");
1168 return *(RegList.List);
1169 }
1170
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001171 unsigned getRegPair() const {
1172 assert((Kind == k_RegPair) && "Invalid access!");
1173 return RegIdx.Index;
1174 }
1175
David Blaikie960ea3f2014-06-08 16:18:35 +00001176 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1177 MipsAsmParser &Parser) {
1178 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001179 Op->Tok.Data = Str.data();
1180 Op->Tok.Length = Str.size();
1181 Op->StartLoc = S;
1182 Op->EndLoc = S;
1183 return Op;
1184 }
1185
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001186 /// Create a numeric register (e.g. $1). The exact register remains
1187 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001188 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001189 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001190 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001191 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001192 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001193 }
1194
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001195 /// Create a register that is definitely a GPR.
1196 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001197 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001198 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001199 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001200 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001201 }
1202
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001203 /// Create a register that is definitely a FGR.
1204 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001205 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001206 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001207 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001208 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1209 }
1210
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001211 /// Create a register that is definitely a HWReg.
1212 /// This is typically only used for named registers such as $hwr_cpunum.
1213 static std::unique_ptr<MipsOperand>
1214 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1215 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1216 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1217 }
1218
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001219 /// Create a register that is definitely an FCC.
1220 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001221 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001222 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001223 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001224 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1225 }
1226
1227 /// Create a register that is definitely an ACC.
1228 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001229 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001230 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001231 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001232 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1233 }
1234
1235 /// Create a register that is definitely an MSA128.
1236 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001237 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001238 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001239 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001240 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1241 }
1242
1243 /// Create a register that is definitely an MSACtrl.
1244 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001245 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001246 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001247 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001248 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1249 }
1250
David Blaikie960ea3f2014-06-08 16:18:35 +00001251 static std::unique_ptr<MipsOperand>
1252 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1253 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001254 Op->Imm.Val = Val;
1255 Op->StartLoc = S;
1256 Op->EndLoc = E;
1257 return Op;
1258 }
1259
David Blaikie960ea3f2014-06-08 16:18:35 +00001260 static std::unique_ptr<MipsOperand>
1261 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1262 SMLoc E, MipsAsmParser &Parser) {
1263 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1264 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001265 Op->Mem.Off = Off;
1266 Op->StartLoc = S;
1267 Op->EndLoc = E;
1268 return Op;
1269 }
1270
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001271 static std::unique_ptr<MipsOperand>
1272 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1273 MipsAsmParser &Parser) {
1274 assert (Regs.size() > 0 && "Empty list not allowed");
1275
1276 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001277 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001278 Op->StartLoc = StartLoc;
1279 Op->EndLoc = EndLoc;
1280 return Op;
1281 }
1282
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001283 static std::unique_ptr<MipsOperand>
1284 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1285 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1286 Op->RegIdx.Index = RegNo;
1287 Op->StartLoc = S;
1288 Op->EndLoc = E;
1289 return Op;
1290 }
1291
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001292 bool isGPRAsmReg() const {
1293 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001294 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001295 bool isMM16AsmReg() const {
1296 if (!(isRegIdx() && RegIdx.Kind))
1297 return false;
1298 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1299 || RegIdx.Index == 16 || RegIdx.Index == 17);
1300 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001301 bool isMM16AsmRegZero() const {
1302 if (!(isRegIdx() && RegIdx.Kind))
1303 return false;
1304 return (RegIdx.Index == 0 ||
1305 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1306 RegIdx.Index == 17);
1307 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001308 bool isMM16AsmRegMoveP() const {
1309 if (!(isRegIdx() && RegIdx.Kind))
1310 return false;
1311 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1312 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1313 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001314 bool isFGRAsmReg() const {
1315 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1316 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001317 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001318 bool isHWRegsAsmReg() const {
1319 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001320 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001321 bool isCCRAsmReg() const {
1322 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001323 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001324 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001325 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1326 return false;
1327 if (!AsmParser.hasEightFccRegisters())
1328 return RegIdx.Index == 0;
1329 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001330 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001331 bool isACCAsmReg() const {
1332 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001333 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001334 bool isCOP0AsmReg() const {
1335 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1336 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001337 bool isCOP2AsmReg() const {
1338 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001339 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001340 bool isCOP3AsmReg() const {
1341 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1342 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001343 bool isMSA128AsmReg() const {
1344 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001345 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001346 bool isMSACtrlAsmReg() const {
1347 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001348 }
1349
Jack Carterb4dbc172012-09-05 23:34:03 +00001350 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001351 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001352 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001353 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001354
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001355 virtual ~MipsOperand() {
1356 switch (Kind) {
1357 case k_Immediate:
1358 break;
1359 case k_Memory:
1360 delete Mem.Base;
1361 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001362 case k_RegList:
1363 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001364 case k_PhysRegister:
1365 case k_RegisterIndex:
1366 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001367 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001368 break;
1369 }
1370 }
1371
Craig Topper56c590a2014-04-29 07:58:02 +00001372 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001373 switch (Kind) {
1374 case k_Immediate:
1375 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001376 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001377 OS << ">";
1378 break;
1379 case k_Memory:
1380 OS << "Mem<";
1381 Mem.Base->print(OS);
1382 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001383 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001384 OS << ">";
1385 break;
1386 case k_PhysRegister:
1387 OS << "PhysReg<" << PhysReg.Num << ">";
1388 break;
1389 case k_RegisterIndex:
1390 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1391 break;
1392 case k_Token:
1393 OS << Tok.Data;
1394 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001395 case k_RegList:
1396 OS << "RegList< ";
1397 for (auto Reg : (*RegList.List))
1398 OS << Reg << " ";
1399 OS << ">";
1400 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001401 case k_RegPair:
1402 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1403 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001404 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001405 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001406}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001407} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001408
Jack Carter9e65aa32013-03-22 00:05:30 +00001409namespace llvm {
1410extern const MCInstrDesc MipsInsts[];
1411}
1412static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1413 return MipsInsts[Opcode];
1414}
1415
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001416static bool hasShortDelaySlot(unsigned Opcode) {
1417 switch (Opcode) {
1418 case Mips::JALS_MM:
1419 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001420 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001421 case Mips::BGEZALS_MM:
1422 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001423 return true;
1424 default:
1425 return false;
1426 }
1427}
1428
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001429static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1430 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1431 return &SRExpr->getSymbol();
1432 }
1433
1434 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1435 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1436 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1437
1438 if (LHSSym)
1439 return LHSSym;
1440
1441 if (RHSSym)
1442 return RHSSym;
1443
1444 return nullptr;
1445 }
1446
1447 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1448 return getSingleMCSymbol(UExpr->getSubExpr());
1449
1450 return nullptr;
1451}
1452
1453static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1454 if (isa<MCSymbolRefExpr>(Expr))
1455 return 1;
1456
1457 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1458 return countMCSymbolRefExpr(BExpr->getLHS()) +
1459 countMCSymbolRefExpr(BExpr->getRHS());
1460
1461 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1462 return countMCSymbolRefExpr(UExpr->getSubExpr());
1463
1464 return 0;
1465}
1466
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001467namespace {
1468void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1469 SmallVectorImpl<MCInst> &Instructions) {
1470 MCInst tmpInst;
1471 tmpInst.setOpcode(Opcode);
1472 tmpInst.addOperand(MCOperand::createReg(Reg0));
1473 tmpInst.addOperand(Op1);
1474 tmpInst.setLoc(IDLoc);
1475 Instructions.push_back(tmpInst);
1476}
1477
1478void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1479 SmallVectorImpl<MCInst> &Instructions) {
1480 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1481}
1482
1483void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1484 SmallVectorImpl<MCInst> &Instructions) {
1485 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1486}
1487
1488void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1489 SmallVectorImpl<MCInst> &Instructions) {
1490 MCInst tmpInst;
1491 tmpInst.setOpcode(Opcode);
1492 tmpInst.addOperand(MCOperand::createImm(Imm1));
1493 tmpInst.addOperand(MCOperand::createImm(Imm2));
1494 tmpInst.setLoc(IDLoc);
1495 Instructions.push_back(tmpInst);
1496}
1497
1498void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1499 SmallVectorImpl<MCInst> &Instructions) {
1500 MCInst tmpInst;
1501 tmpInst.setOpcode(Opcode);
1502 tmpInst.addOperand(MCOperand::createReg(Reg0));
1503 tmpInst.setLoc(IDLoc);
1504 Instructions.push_back(tmpInst);
1505}
1506
1507void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1508 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1509 MCInst tmpInst;
1510 tmpInst.setOpcode(Opcode);
1511 tmpInst.addOperand(MCOperand::createReg(Reg0));
1512 tmpInst.addOperand(MCOperand::createReg(Reg1));
1513 tmpInst.addOperand(Op2);
1514 tmpInst.setLoc(IDLoc);
1515 Instructions.push_back(tmpInst);
1516}
1517
1518void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1519 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1520 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1521 Instructions);
1522}
1523
1524void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1525 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1526 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1527 Instructions);
1528}
1529
1530void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1531 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1532 if (ShiftAmount >= 32) {
1533 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1534 Instructions);
1535 return;
1536 }
1537
1538 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1539}
1540} // end anonymous namespace.
1541
Jack Carter9e65aa32013-03-22 00:05:30 +00001542bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001543 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001544 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001545 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001546
Jack Carter9e65aa32013-03-22 00:05:30 +00001547 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001548
1549 if (MCID.isBranch() || MCID.isCall()) {
1550 const unsigned Opcode = Inst.getOpcode();
1551 MCOperand Offset;
1552
1553 switch (Opcode) {
1554 default:
1555 break;
Kai Nackee0245392015-01-27 19:11:28 +00001556 case Mips::BBIT0:
1557 case Mips::BBIT032:
1558 case Mips::BBIT1:
1559 case Mips::BBIT132:
1560 assert(hasCnMips() && "instruction only valid for octeon cpus");
1561 // Fall through
1562
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001563 case Mips::BEQ:
1564 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001565 case Mips::BEQ_MM:
1566 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001567 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001568 Offset = Inst.getOperand(2);
1569 if (!Offset.isImm())
1570 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001571 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001572 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001573 if (OffsetToAlignment(Offset.getImm(),
1574 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001575 return Error(IDLoc, "branch to misaligned address");
1576 break;
1577 case Mips::BGEZ:
1578 case Mips::BGTZ:
1579 case Mips::BLEZ:
1580 case Mips::BLTZ:
1581 case Mips::BGEZAL:
1582 case Mips::BLTZAL:
1583 case Mips::BC1F:
1584 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001585 case Mips::BGEZ_MM:
1586 case Mips::BGTZ_MM:
1587 case Mips::BLEZ_MM:
1588 case Mips::BLTZ_MM:
1589 case Mips::BGEZAL_MM:
1590 case Mips::BLTZAL_MM:
1591 case Mips::BC1F_MM:
1592 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001593 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001594 Offset = Inst.getOperand(1);
1595 if (!Offset.isImm())
1596 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001597 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001598 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001599 if (OffsetToAlignment(Offset.getImm(),
1600 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001601 return Error(IDLoc, "branch to misaligned address");
1602 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001603 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001604 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001605 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001606 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001607 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1608 Offset = Inst.getOperand(1);
1609 if (!Offset.isImm())
1610 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001611 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001612 return Error(IDLoc, "branch target out of range");
1613 if (OffsetToAlignment(Offset.getImm(), 2LL))
1614 return Error(IDLoc, "branch to misaligned address");
1615 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001616 }
1617 }
1618
Daniel Sandersa84989a2014-06-16 13:25:35 +00001619 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1620 // We still accept it but it is a normal nop.
1621 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1622 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1623 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1624 "nop instruction");
1625 }
1626
Kai Nackee0245392015-01-27 19:11:28 +00001627 if (hasCnMips()) {
1628 const unsigned Opcode = Inst.getOpcode();
1629 MCOperand Opnd;
1630 int Imm;
1631
1632 switch (Opcode) {
1633 default:
1634 break;
1635
1636 case Mips::BBIT0:
1637 case Mips::BBIT032:
1638 case Mips::BBIT1:
1639 case Mips::BBIT132:
1640 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1641 // The offset is handled above
1642 Opnd = Inst.getOperand(1);
1643 if (!Opnd.isImm())
1644 return Error(IDLoc, "expected immediate operand kind");
1645 Imm = Opnd.getImm();
1646 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1647 Opcode == Mips::BBIT1 ? 63 : 31))
1648 return Error(IDLoc, "immediate operand value out of range");
1649 if (Imm > 31) {
1650 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1651 : Mips::BBIT132);
1652 Inst.getOperand(1).setImm(Imm - 32);
1653 }
1654 break;
1655
Kai Nackee0245392015-01-27 19:11:28 +00001656 case Mips::SEQi:
1657 case Mips::SNEi:
1658 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1659 Opnd = Inst.getOperand(2);
1660 if (!Opnd.isImm())
1661 return Error(IDLoc, "expected immediate operand kind");
1662 Imm = Opnd.getImm();
1663 if (!isInt<10>(Imm))
1664 return Error(IDLoc, "immediate operand value out of range");
1665 break;
1666 }
1667 }
1668
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001669 // This expansion is not in a function called by tryExpandInstruction()
1670 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001671 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1672 inPicMode()) {
1673 warnIfNoMacro(IDLoc);
1674
1675 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1676
1677 // We can do this expansion if there's only 1 symbol in the argument
1678 // expression.
1679 if (countMCSymbolRefExpr(JalExpr) > 1)
1680 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1681
1682 // FIXME: This is checking the expression can be handled by the later stages
1683 // of the assembler. We ought to leave it to those later stages but
1684 // we can't do that until we stop evaluateRelocExpr() rewriting the
1685 // expressions into non-equivalent forms.
1686 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1687
1688 // FIXME: Add support for label+offset operands (currently causes an error).
1689 // FIXME: Add support for forward-declared local symbols.
1690 // FIXME: Add expansion for when the LargeGOT option is enabled.
1691 if (JalSym->isInSection() || JalSym->isTemporary()) {
1692 if (isABI_O32()) {
1693 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001694 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001695 // R_(MICRO)MIPS_GOT16 label
1696 // addiu $25, $25, 0
1697 // R_(MICRO)MIPS_LO16 label
1698 // jalr $25
1699 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1700 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1701
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001702 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1703 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1704 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1705 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001706 } else if (isABI_N32() || isABI_N64()) {
1707 // If it's a local symbol and the N32/N64 ABIs are being used,
1708 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001709 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001710 // R_(MICRO)MIPS_GOT_DISP label
1711 // jalr $25
1712 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1713
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001714 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1715 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001716 }
1717 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001718 // If it's an external/weak symbol, we expand to:
1719 // lw/ld $25, 0($gp)
1720 // R_(MICRO)MIPS_CALL16 label
1721 // jalr $25
1722 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001723
Daniel Sandersb7002032015-11-20 13:16:35 +00001724 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1725 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
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.
1756 expandMemInst(Inst, IDLoc, Instructions, 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.
1766 expandMemInst(Inst, IDLoc, Instructions, 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)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001770 expandMemInst(Inst, IDLoc, Instructions, 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
1796 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1797 IDLoc, Instructions);
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;
1813 case Mips::ADDIUS5_MM:
1814 Opnd = Inst.getOperand(2);
1815 if (!Opnd.isImm())
1816 return Error(IDLoc, "expected immediate operand kind");
1817 Imm = Opnd.getImm();
1818 if (Imm < -8 || Imm > 7)
1819 return Error(IDLoc, "immediate operand value out of range");
1820 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001821 case Mips::ADDIUSP_MM:
1822 Opnd = Inst.getOperand(0);
1823 if (!Opnd.isImm())
1824 return Error(IDLoc, "expected immediate operand kind");
1825 Imm = Opnd.getImm();
1826 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1827 Imm % 4 != 0)
1828 return Error(IDLoc, "immediate operand value out of range");
1829 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001830 case Mips::SLL16_MM:
1831 case Mips::SRL16_MM:
1832 Opnd = Inst.getOperand(2);
1833 if (!Opnd.isImm())
1834 return Error(IDLoc, "expected immediate operand kind");
1835 Imm = Opnd.getImm();
1836 if (Imm < 1 || Imm > 8)
1837 return Error(IDLoc, "immediate operand value out of range");
1838 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001839 case Mips::LI16_MM:
1840 Opnd = Inst.getOperand(1);
1841 if (!Opnd.isImm())
1842 return Error(IDLoc, "expected immediate operand kind");
1843 Imm = Opnd.getImm();
1844 if (Imm < -1 || Imm > 126)
1845 return Error(IDLoc, "immediate operand value out of range");
1846 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001847 case Mips::ADDIUR2_MM:
1848 Opnd = Inst.getOperand(2);
1849 if (!Opnd.isImm())
1850 return Error(IDLoc, "expected immediate operand kind");
1851 Imm = Opnd.getImm();
1852 if (!(Imm == 1 || Imm == -1 ||
1853 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1854 return Error(IDLoc, "immediate operand value out of range");
1855 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001856 case Mips::ADDIUR1SP_MM:
1857 Opnd = Inst.getOperand(1);
1858 if (!Opnd.isImm())
1859 return Error(IDLoc, "expected immediate operand kind");
1860 Imm = Opnd.getImm();
1861 if (OffsetToAlignment(Imm, 4LL))
1862 return Error(IDLoc, "misaligned immediate operand value");
1863 if (Imm < 0 || Imm > 255)
1864 return Error(IDLoc, "immediate operand value out of range");
1865 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001866 case Mips::ANDI16_MM:
1867 Opnd = Inst.getOperand(2);
1868 if (!Opnd.isImm())
1869 return Error(IDLoc, "expected immediate operand kind");
1870 Imm = Opnd.getImm();
1871 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1872 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1873 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1874 return Error(IDLoc, "immediate operand value out of range");
1875 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001876 case Mips::LBU16_MM:
1877 Opnd = Inst.getOperand(2);
1878 if (!Opnd.isImm())
1879 return Error(IDLoc, "expected immediate operand kind");
1880 Imm = Opnd.getImm();
1881 if (Imm < -1 || Imm > 14)
1882 return Error(IDLoc, "immediate operand value out of range");
1883 break;
1884 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001885 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001886 Opnd = Inst.getOperand(2);
1887 if (!Opnd.isImm())
1888 return Error(IDLoc, "expected immediate operand kind");
1889 Imm = Opnd.getImm();
1890 if (Imm < 0 || Imm > 15)
1891 return Error(IDLoc, "immediate operand value out of range");
1892 break;
1893 case Mips::LHU16_MM:
1894 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001895 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001896 Opnd = Inst.getOperand(2);
1897 if (!Opnd.isImm())
1898 return Error(IDLoc, "expected immediate operand kind");
1899 Imm = Opnd.getImm();
1900 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1901 return Error(IDLoc, "immediate operand value out of range");
1902 break;
1903 case Mips::LW16_MM:
1904 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001905 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001906 Opnd = Inst.getOperand(2);
1907 if (!Opnd.isImm())
1908 return Error(IDLoc, "expected immediate operand kind");
1909 Imm = Opnd.getImm();
1910 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1911 return Error(IDLoc, "immediate operand value out of range");
1912 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001913 case Mips::ADDIUPC_MM:
1914 MCOperand Opnd = Inst.getOperand(1);
1915 if (!Opnd.isImm())
1916 return Error(IDLoc, "expected immediate operand kind");
1917 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001918 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001919 return Error(IDLoc, "immediate operand value out of range");
1920 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001921 }
1922 }
1923
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001924 MacroExpanderResultTy ExpandResult =
1925 tryExpandInstruction(Inst, IDLoc, Instructions);
1926 switch (ExpandResult) {
1927 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001928 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001929 break;
1930 case MER_Success:
1931 break;
1932 case MER_Fail:
1933 return true;
1934 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001935
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001936 // If this instruction has a delay slot and .set reorder is active,
1937 // emit a NOP after it.
1938 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1939 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1940
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001941 if ((Inst.getOpcode() == Mips::JalOneReg ||
1942 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1943 isPicAndNotNxxAbi()) {
1944 if (IsCpRestoreSet) {
1945 // We need a NOP between the JALR and the LW:
1946 // If .set reorder has been used, we've already emitted a NOP.
1947 // If .set noreorder has been used, we need to emit a NOP at this point.
1948 if (!AssemblerOptions.back()->isReorder())
1949 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1950
1951 // Load the $gp from the stack.
1952 SmallVector<MCInst, 3> LoadInsts;
1953 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1954 IDLoc, LoadInsts);
1955
1956 for (const MCInst &Inst : LoadInsts)
1957 Instructions.push_back(Inst);
1958
1959 } else
1960 Warning(IDLoc, "no .cprestore used in PIC mode");
1961 }
1962
Jack Carter9e65aa32013-03-22 00:05:30 +00001963 return false;
1964}
1965
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001966MipsAsmParser::MacroExpanderResultTy
1967MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1968 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001969 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001970 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001971 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001972 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001973 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1974 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001975 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001976 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1977 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001978 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001979 case Mips::LoadAddrImm64:
1980 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1981 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1982 "expected immediate operand kind");
1983
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001984 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1985 Inst.getOperand(1),
1986 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1987 Instructions)
1988 ? MER_Fail
1989 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001990 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001991 case Mips::LoadAddrReg64:
1992 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1993 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1994 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1995 "expected immediate operand kind");
1996
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001997 return expandLoadAddress(Inst.getOperand(0).getReg(),
1998 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1999 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
2000 Instructions)
2001 ? MER_Fail
2002 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002003 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002004 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002005 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
2006 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002007 case Mips::SWM_MM:
2008 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002009 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
2010 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002011 case Mips::JalOneReg:
2012 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002013 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
2014 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002015 case Mips::BneImm:
2016 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002017 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002018 case Mips::BLT:
2019 case Mips::BLE:
2020 case Mips::BGE:
2021 case Mips::BGT:
2022 case Mips::BLTU:
2023 case Mips::BLEU:
2024 case Mips::BGEU:
2025 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002026 case Mips::BLTL:
2027 case Mips::BLEL:
2028 case Mips::BGEL:
2029 case Mips::BGTL:
2030 case Mips::BLTUL:
2031 case Mips::BLEUL:
2032 case Mips::BGEUL:
2033 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002034 case Mips::BLTImmMacro:
2035 case Mips::BLEImmMacro:
2036 case Mips::BGEImmMacro:
2037 case Mips::BGTImmMacro:
2038 case Mips::BLTUImmMacro:
2039 case Mips::BLEUImmMacro:
2040 case Mips::BGEUImmMacro:
2041 case Mips::BGTUImmMacro:
2042 case Mips::BLTLImmMacro:
2043 case Mips::BLELImmMacro:
2044 case Mips::BGELImmMacro:
2045 case Mips::BGTLImmMacro:
2046 case Mips::BLTULImmMacro:
2047 case Mips::BLEULImmMacro:
2048 case Mips::BGEULImmMacro:
2049 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002050 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2051 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002052 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002053 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2054 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002055 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002056 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2057 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002058 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002059 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2060 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002061 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002062 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2063 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002064 case Mips::PseudoTRUNC_W_S:
2065 return expandTrunc(Inst, false, false, IDLoc, Instructions) ? MER_Fail
2066 : MER_Success;
2067 case Mips::PseudoTRUNC_W_D32:
2068 return expandTrunc(Inst, true, false, IDLoc, Instructions) ? MER_Fail
2069 : MER_Success;
2070 case Mips::PseudoTRUNC_W_D:
2071 return expandTrunc(Inst, true, true, IDLoc, Instructions) ? MER_Fail
2072 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002073 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002074 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002075 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002076 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002077 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002078 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2079 case Mips::NORImm:
2080 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2081 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002082 case Mips::ADDi:
2083 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002084 case Mips::SLTi:
2085 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002086 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2087 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2088 int64_t ImmValue = Inst.getOperand(2).getImm();
2089 if (isInt<16>(ImmValue))
2090 return MER_NotAMacro;
2091 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2092 : MER_Success;
2093 }
2094 return MER_NotAMacro;
2095 case Mips::ANDi:
2096 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002097 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002098 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2099 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2100 int64_t ImmValue = Inst.getOperand(2).getImm();
2101 if (isUInt<16>(ImmValue))
2102 return MER_NotAMacro;
2103 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2104 : MER_Success;
2105 }
2106 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002107 case Mips::ROL:
2108 case Mips::ROR:
2109 return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail
2110 : MER_Success;
2111 case Mips::ROLImm:
2112 case Mips::RORImm:
2113 return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2114 : MER_Success;
2115 case Mips::DROL:
2116 case Mips::DROR:
2117 return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail
2118 : MER_Success;
2119 case Mips::DROLImm:
2120 case Mips::DRORImm:
2121 return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2122 : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002123 case Mips::ABSMacro:
2124 return expandAbs(Inst, IDLoc, Instructions) ? MER_Fail
2125 : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002126 }
Jack Carter30a59822012-10-04 04:03:53 +00002127}
Jack Carter92995f12012-10-06 00:53:28 +00002128
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002129bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2130 SmallVectorImpl<MCInst> &Instructions) {
2131 // Create a JALR instruction which is going to replace the pseudo-JAL.
2132 MCInst JalrInst;
2133 JalrInst.setLoc(IDLoc);
2134 const MCOperand FirstRegOp = Inst.getOperand(0);
2135 const unsigned Opcode = Inst.getOpcode();
2136
2137 if (Opcode == Mips::JalOneReg) {
2138 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002139 if (IsCpRestoreSet && inMicroMipsMode()) {
2140 JalrInst.setOpcode(Mips::JALRS16_MM);
2141 JalrInst.addOperand(FirstRegOp);
2142 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002143 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002144 JalrInst.addOperand(FirstRegOp);
2145 } else {
2146 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002147 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002148 JalrInst.addOperand(FirstRegOp);
2149 }
2150 } else if (Opcode == Mips::JalTwoReg) {
2151 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002152 if (IsCpRestoreSet && inMicroMipsMode())
2153 JalrInst.setOpcode(Mips::JALRS_MM);
2154 else
2155 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002156 JalrInst.addOperand(FirstRegOp);
2157 const MCOperand SecondRegOp = Inst.getOperand(1);
2158 JalrInst.addOperand(SecondRegOp);
2159 }
2160 Instructions.push_back(JalrInst);
2161
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002162 // If .set reorder is active and branch instruction has a delay slot,
2163 // emit a NOP after it.
2164 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2165 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002166 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002167 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002168
2169 return false;
2170}
2171
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002172/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002173template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002174 unsigned BitNum = findFirstSet(x);
2175
2176 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2177}
2178
2179/// Load (or add) an immediate into a register.
2180///
2181/// @param ImmValue The immediate to load.
2182/// @param DstReg The register that will hold the immediate.
2183/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2184/// for a simple initialization.
2185/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2186/// @param IsAddress True if the immediate represents an address. False if it
2187/// is an integer.
2188/// @param IDLoc Location of the immediate in the source file.
2189/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002190bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002191 unsigned SrcReg, bool Is32BitImm,
2192 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002193 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002194 if (!Is32BitImm && !isGP64bit()) {
2195 Error(IDLoc, "instruction requires a 64-bit architecture");
2196 return true;
2197 }
2198
Daniel Sanders03f9c012015-07-14 12:24:22 +00002199 if (Is32BitImm) {
2200 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2201 // Sign extend up to 64-bit so that the predicates match the hardware
2202 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2203 // true.
2204 ImmValue = SignExtend64<32>(ImmValue);
2205 } else {
2206 Error(IDLoc, "instruction requires a 32-bit immediate");
2207 return true;
2208 }
2209 }
2210
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002211 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2212 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2213
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002214 bool UseSrcReg = false;
2215 if (SrcReg != Mips::NoRegister)
2216 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002217
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002218 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002219 if (UseSrcReg &&
2220 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002221 // At this point we need AT to perform the expansions and we exit if it is
2222 // not available.
2223 unsigned ATReg = getATReg(IDLoc);
2224 if (!ATReg)
2225 return true;
2226 TmpReg = ATReg;
2227 }
2228
Daniel Sanders03f9c012015-07-14 12:24:22 +00002229 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002230 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002231 SrcReg = ZeroReg;
2232
2233 // This doesn't quite follow the usual ABI expectations for N32 but matches
2234 // traditional assembler behaviour. N32 would normally use addiu for both
2235 // integers and addresses.
2236 if (IsAddress && !Is32BitImm) {
2237 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2238 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002239 }
2240
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002241 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2242 return false;
2243 }
2244
2245 if (isUInt<16>(ImmValue)) {
2246 unsigned TmpReg = DstReg;
2247 if (SrcReg == DstReg) {
2248 TmpReg = getATReg(IDLoc);
2249 if (!TmpReg)
2250 return true;
2251 }
2252
2253 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002254 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002255 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2256 return false;
2257 }
2258
2259 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002260 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002261
Toma Tabacu79588102015-04-29 10:19:56 +00002262 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2263 uint16_t Bits15To0 = ImmValue & 0xffff;
2264
Toma Tabacua3d056f2015-05-15 09:42:11 +00002265 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002266 // Traditional behaviour seems to special case this particular value. It's
2267 // not clear why other masks are handled differently.
2268 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002269 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002270 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2271 if (UseSrcReg)
2272 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2273 return false;
2274 }
2275
2276 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002277 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002278 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002279 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002280 if (Bits15To0)
2281 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2282 if (UseSrcReg)
2283 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2284 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002285 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002286
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002287 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2288 if (Bits15To0)
2289 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002290 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002291 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2292 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002293 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002294
2295 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2296 if (Is32BitImm) {
2297 Error(IDLoc, "instruction requires a 32-bit immediate");
2298 return true;
2299 }
2300
2301 // Traditionally, these immediates are shifted as little as possible and as
2302 // such we align the most significant bit to bit 15 of our temporary.
2303 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2304 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2305 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2306 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2307 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2308 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2309
2310 if (UseSrcReg)
2311 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2312
2313 return false;
2314 }
2315
2316 warnIfNoMacro(IDLoc);
2317
2318 // The remaining case is packed with a sequence of dsll and ori with zeros
2319 // being omitted and any neighbouring dsll's being coalesced.
2320 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2321
2322 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2323 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2324 IDLoc, Instructions))
2325 return false;
2326
2327 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2328 // skip it and defer the shift to the next chunk.
2329 unsigned ShiftCarriedForwards = 16;
2330 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2331 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2332
2333 if (ImmChunk != 0) {
2334 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2335 Instructions);
2336 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2337 ShiftCarriedForwards = 0;
2338 }
2339
2340 ShiftCarriedForwards += 16;
2341 }
2342 ShiftCarriedForwards -= 16;
2343
2344 // Finish any remaining shifts left by trailing zeros.
2345 if (ShiftCarriedForwards)
2346 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2347 Instructions);
2348
2349 if (UseSrcReg)
2350 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2351
Matheus Almeida3813d572014-06-19 14:39:14 +00002352 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002353}
Jack Carter92995f12012-10-06 00:53:28 +00002354
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002355bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2356 SmallVectorImpl<MCInst> &Instructions) {
2357 const MCOperand &ImmOp = Inst.getOperand(1);
2358 assert(ImmOp.isImm() && "expected immediate operand kind");
2359 const MCOperand &DstRegOp = Inst.getOperand(0);
2360 assert(DstRegOp.isReg() && "expected register operand kind");
2361
2362 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002363 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002364 return true;
2365
2366 return false;
2367}
2368
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002369bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2370 const MCOperand &Offset,
2371 bool Is32BitAddress, SMLoc IDLoc,
2372 SmallVectorImpl<MCInst> &Instructions) {
2373 // la can't produce a usable address when addresses are 64-bit.
2374 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2375 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2376 // We currently can't do this because we depend on the equality
2377 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2378 Error(IDLoc, "la used to load 64-bit address");
2379 // Continue as if we had 'dla' instead.
2380 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002381 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002382
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002383 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002384 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002385 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002386 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002387 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002388
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002389 if (!Offset.isImm())
2390 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2391 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002392
Scott Egerton24557012016-01-21 15:11:01 +00002393 if (!ABI.ArePtrs64bit()) {
2394 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2395 Is32BitAddress = true;
2396 }
2397
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002398 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2399 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002400}
2401
Toma Tabacuf712ede2015-06-17 14:31:51 +00002402bool MipsAsmParser::loadAndAddSymbolAddress(
2403 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2404 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002405 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002406
Daniel Sandersd5a89412015-10-05 13:19:29 +00002407 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2408 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2409 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2410 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2411 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002412
Toma Tabacufb9d1252015-06-22 12:08:39 +00002413 bool UseSrcReg = SrcReg != Mips::NoRegister;
2414
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002415 // This is the 64-bit symbol address expansion.
2416 if (ABI.ArePtrs64bit() && isGP64bit()) {
2417 // We always need AT for the 64-bit expansion.
2418 // If it is not available we exit.
2419 unsigned ATReg = getATReg(IDLoc);
2420 if (!ATReg)
2421 return true;
2422
Daniel Sandersd5a89412015-10-05 13:19:29 +00002423 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2424 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2425 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2426 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002427
Scott Egerton24557012016-01-21 15:11:01 +00002428 if (UseSrcReg &&
2429 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2430 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002431 // If $rs is the same as $rd:
2432 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2433 // daddiu $at, $at, %higher(sym)
2434 // dsll $at, $at, 16
2435 // daddiu $at, $at, %hi(sym)
2436 // dsll $at, $at, 16
2437 // daddiu $at, $at, %lo(sym)
2438 // daddu $rd, $at, $rd
2439 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2440 Instructions);
2441 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2442 IDLoc, Instructions);
2443 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2444 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2445 Instructions);
2446 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2447 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2448 Instructions);
2449 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2450
2451 return false;
2452 }
2453
2454 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2455 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2456 // lui $at, %hi(sym)
2457 // daddiu $rd, $rd, %higher(sym)
2458 // daddiu $at, $at, %lo(sym)
2459 // dsll32 $rd, $rd, 0
2460 // daddu $rd, $rd, $at
2461 // (daddu $rd, $rd, $rs)
2462 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2463 Instructions);
2464 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2465 Instructions);
2466 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2467 IDLoc, Instructions);
2468 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2469 Instructions);
2470 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2471 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2472 if (UseSrcReg)
2473 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2474
2475 return false;
2476 }
2477
2478 // And now, the 32-bit symbol address expansion:
2479 // If $rs is the same as $rd:
2480 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2481 // ori $at, $at, %lo(sym)
2482 // addu $rd, $at, $rd
2483 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2484 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2485 // ori $rd, $rd, %lo(sym)
2486 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002487 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002488 if (UseSrcReg &&
2489 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002490 // If $rs is the same as $rd, we need to use AT.
2491 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002492 unsigned ATReg = getATReg(IDLoc);
2493 if (!ATReg)
2494 return true;
2495 TmpReg = ATReg;
2496 }
2497
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002498 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2499 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2500 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002501
Toma Tabacufb9d1252015-06-22 12:08:39 +00002502 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002503 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2504 else
Scott Egerton24557012016-01-21 15:11:01 +00002505 assert(
2506 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002507
Toma Tabacu674825c2015-06-16 12:16:24 +00002508 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002509}
2510
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002511bool MipsAsmParser::expandUncondBranchMMPseudo(
2512 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002513 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2514 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002515
2516 MCOperand Offset = Inst.getOperand(0);
2517 if (Offset.isExpr()) {
2518 Inst.clear();
2519 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002520 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2521 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2522 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002523 } else {
2524 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002525 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002526 // If offset fits into 11 bits then this instruction becomes microMIPS
2527 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002528 if (inMicroMipsMode())
2529 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002530 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002531 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002532 Error(IDLoc, "branch target out of range");
2533 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2534 Error(IDLoc, "branch to misaligned address");
2535 Inst.clear();
2536 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002537 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2538 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2539 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002540 }
2541 }
2542 Instructions.push_back(Inst);
2543
Zoran Jovanovicada70912015-09-07 11:56:37 +00002544 // If .set reorder is active and branch instruction has a delay slot,
2545 // emit a NOP after it.
2546 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2547 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002548 createNop(true, IDLoc, Instructions);
2549
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002550 return false;
2551}
2552
Toma Tabacue1e460d2015-06-11 10:36:10 +00002553bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2554 SmallVectorImpl<MCInst> &Instructions) {
2555 const MCOperand &DstRegOp = Inst.getOperand(0);
2556 assert(DstRegOp.isReg() && "expected register operand kind");
2557
2558 const MCOperand &ImmOp = Inst.getOperand(1);
2559 assert(ImmOp.isImm() && "expected immediate operand kind");
2560
2561 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2562 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2563
2564 unsigned OpCode = 0;
2565 switch(Inst.getOpcode()) {
2566 case Mips::BneImm:
2567 OpCode = Mips::BNE;
2568 break;
2569 case Mips::BeqImm:
2570 OpCode = Mips::BEQ;
2571 break;
2572 default:
2573 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2574 break;
2575 }
2576
2577 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002578 if (ImmValue == 0)
2579 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2580 Instructions);
2581 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002582 warnIfNoMacro(IDLoc);
2583
2584 unsigned ATReg = getATReg(IDLoc);
2585 if (!ATReg)
2586 return true;
2587
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002588 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2589 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002590 return true;
2591
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002592 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002593 }
2594 return false;
2595}
2596
Jack Carter9e65aa32013-03-22 00:05:30 +00002597void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002598 SmallVectorImpl<MCInst> &Instructions,
2599 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002600 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002601 const MCExpr *ExprOffset;
2602 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002603 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002604 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2605 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002606 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002607 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2608 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002609 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002610 if (isImmOpnd) {
2611 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2612 ImmOffset = Inst.getOperand(2).getImm();
2613 LoOffset = ImmOffset & 0x0000ffff;
2614 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002615 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002616 if (LoOffset & 0x8000)
2617 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002618 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002619 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002620 // These are some of the types of expansions we perform here:
2621 // 1) lw $8, sym => lui $8, %hi(sym)
2622 // lw $8, %lo(sym)($8)
2623 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2624 // add $8, $8, $9
2625 // lw $8, %lo(offset)($9)
2626 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2627 // add $at, $at, $8
2628 // lw $8, %lo(offset)($at)
2629 // 4) sw $8, sym => lui $at, %hi(sym)
2630 // sw $8, %lo(sym)($at)
2631 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2632 // add $at, $at, $8
2633 // sw $8, %lo(offset)($at)
2634 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2635 // ldc1 $f0, %lo(sym)($at)
2636 //
2637 // For load instructions we can use the destination register as a temporary
2638 // if base and dst are different (examples 1 and 2) and if the base register
2639 // is general purpose otherwise we must use $at (example 6) and error if it's
2640 // not available. For stores we must use $at (examples 4 and 5) because we
2641 // must not clobber the source register setting up the offset.
2642 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2643 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2644 unsigned RegClassIDOp0 =
2645 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2646 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2647 (RegClassIDOp0 == Mips::GPR64RegClassID);
2648 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002649 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002650 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002651 // At this point we need AT to perform the expansions and we exit if it is
2652 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002653 TmpRegNum = getATReg(IDLoc);
2654 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002655 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002656 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002657
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002658 emitRX(Mips::LUi, TmpRegNum,
2659 isImmOpnd ? MCOperand::createImm(HiOffset)
2660 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2661 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002662 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002663 if (BaseRegNum != Mips::ZERO)
2664 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002665 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002666 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002667 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2668 isImmOpnd
2669 ? MCOperand::createImm(LoOffset)
2670 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2671 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002672}
2673
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002674bool
2675MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2676 SmallVectorImpl<MCInst> &Instructions) {
2677 unsigned OpNum = Inst.getNumOperands();
2678 unsigned Opcode = Inst.getOpcode();
2679 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2680
2681 assert (Inst.getOperand(OpNum - 1).isImm() &&
2682 Inst.getOperand(OpNum - 2).isReg() &&
2683 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2684
2685 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2686 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002687 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2688 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2689 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2690 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002691 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002692 if (inMicroMipsMode() && hasMips32r6())
2693 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2694 else
2695 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2696 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002697
2698 Inst.setOpcode(NewOpcode);
2699 Instructions.push_back(Inst);
2700 return false;
2701}
2702
Toma Tabacu1a108322015-06-17 13:20:24 +00002703bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2704 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002705 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002706 unsigned PseudoOpcode = Inst.getOpcode();
2707 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002708 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002709 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2710
2711 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002712 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002713
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002714 unsigned TrgReg;
2715 if (TrgOp.isReg())
2716 TrgReg = TrgOp.getReg();
2717 else if (TrgOp.isImm()) {
2718 warnIfNoMacro(IDLoc);
2719 EmittedNoMacroWarning = true;
2720
2721 TrgReg = getATReg(IDLoc);
2722 if (!TrgReg)
2723 return true;
2724
2725 switch(PseudoOpcode) {
2726 default:
2727 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2728 case Mips::BLTImmMacro:
2729 PseudoOpcode = Mips::BLT;
2730 break;
2731 case Mips::BLEImmMacro:
2732 PseudoOpcode = Mips::BLE;
2733 break;
2734 case Mips::BGEImmMacro:
2735 PseudoOpcode = Mips::BGE;
2736 break;
2737 case Mips::BGTImmMacro:
2738 PseudoOpcode = Mips::BGT;
2739 break;
2740 case Mips::BLTUImmMacro:
2741 PseudoOpcode = Mips::BLTU;
2742 break;
2743 case Mips::BLEUImmMacro:
2744 PseudoOpcode = Mips::BLEU;
2745 break;
2746 case Mips::BGEUImmMacro:
2747 PseudoOpcode = Mips::BGEU;
2748 break;
2749 case Mips::BGTUImmMacro:
2750 PseudoOpcode = Mips::BGTU;
2751 break;
2752 case Mips::BLTLImmMacro:
2753 PseudoOpcode = Mips::BLTL;
2754 break;
2755 case Mips::BLELImmMacro:
2756 PseudoOpcode = Mips::BLEL;
2757 break;
2758 case Mips::BGELImmMacro:
2759 PseudoOpcode = Mips::BGEL;
2760 break;
2761 case Mips::BGTLImmMacro:
2762 PseudoOpcode = Mips::BGTL;
2763 break;
2764 case Mips::BLTULImmMacro:
2765 PseudoOpcode = Mips::BLTUL;
2766 break;
2767 case Mips::BLEULImmMacro:
2768 PseudoOpcode = Mips::BLEUL;
2769 break;
2770 case Mips::BGEULImmMacro:
2771 PseudoOpcode = Mips::BGEUL;
2772 break;
2773 case Mips::BGTULImmMacro:
2774 PseudoOpcode = Mips::BGTUL;
2775 break;
2776 }
2777
2778 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2779 false, IDLoc, Instructions))
2780 return true;
2781 }
2782
Toma Tabacu1a108322015-06-17 13:20:24 +00002783 switch (PseudoOpcode) {
2784 case Mips::BLT:
2785 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002786 case Mips::BLTL:
2787 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002788 AcceptsEquality = false;
2789 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002790 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2791 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002792 ZeroSrcOpcode = Mips::BGTZ;
2793 ZeroTrgOpcode = Mips::BLTZ;
2794 break;
2795 case Mips::BLE:
2796 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002797 case Mips::BLEL:
2798 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002799 AcceptsEquality = true;
2800 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002801 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2802 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002803 ZeroSrcOpcode = Mips::BGEZ;
2804 ZeroTrgOpcode = Mips::BLEZ;
2805 break;
2806 case Mips::BGE:
2807 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002808 case Mips::BGEL:
2809 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002810 AcceptsEquality = true;
2811 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002812 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2813 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002814 ZeroSrcOpcode = Mips::BLEZ;
2815 ZeroTrgOpcode = Mips::BGEZ;
2816 break;
2817 case Mips::BGT:
2818 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002819 case Mips::BGTL:
2820 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002821 AcceptsEquality = false;
2822 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002823 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2824 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002825 ZeroSrcOpcode = Mips::BLTZ;
2826 ZeroTrgOpcode = Mips::BGTZ;
2827 break;
2828 default:
2829 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2830 }
2831
Toma Tabacu1a108322015-06-17 13:20:24 +00002832 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2833 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2834 if (IsSrcRegZero && IsTrgRegZero) {
2835 // FIXME: All of these Opcode-specific if's are needed for compatibility
2836 // with GAS' behaviour. However, they may not generate the most efficient
2837 // code in some circumstances.
2838 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002839 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2840 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002841 return false;
2842 }
2843 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002844 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2845 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002846 Warning(IDLoc, "branch is always taken");
2847 return false;
2848 }
2849 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002850 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2851 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002852 Warning(IDLoc, "branch is always taken");
2853 return false;
2854 }
2855 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002856 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2857 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002858 return false;
2859 }
2860 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002861 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2862 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002863 return false;
2864 }
2865 if (AcceptsEquality) {
2866 // If both registers are $0 and the pseudo-branch accepts equality, it
2867 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002868 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2869 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002870 Warning(IDLoc, "branch is always taken");
2871 return false;
2872 }
2873 // If both registers are $0 and the pseudo-branch does not accept
2874 // equality, it will never be taken, so we don't have to emit anything.
2875 return false;
2876 }
2877 if (IsSrcRegZero || IsTrgRegZero) {
2878 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2879 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2880 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2881 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2882 // the pseudo-branch will never be taken, so we don't emit anything.
2883 // This only applies to unsigned pseudo-branches.
2884 return false;
2885 }
2886 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2887 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2888 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2889 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2890 // the pseudo-branch will always be taken, so we emit an unconditional
2891 // branch.
2892 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002893 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2894 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002895 Warning(IDLoc, "branch is always taken");
2896 return false;
2897 }
2898 if (IsUnsigned) {
2899 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2900 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2901 // the pseudo-branch will be taken only when the non-zero register is
2902 // different from 0, so we emit a BNEZ.
2903 //
2904 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2905 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2906 // the pseudo-branch will be taken only when the non-zero register is
2907 // equal to 0, so we emit a BEQZ.
2908 //
2909 // Because only BLEU and BGEU branch on equality, we can use the
2910 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002911 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2912 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2913 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002914 return false;
2915 }
2916 // If we have a signed pseudo-branch and one of the registers is $0,
2917 // we can use an appropriate compare-to-zero branch. We select which one
2918 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002919 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2920 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2921 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002922 return false;
2923 }
2924
2925 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2926 // expansions. If it is not available, we return.
2927 unsigned ATRegNum = getATReg(IDLoc);
2928 if (!ATRegNum)
2929 return true;
2930
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002931 if (!EmittedNoMacroWarning)
2932 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002933
2934 // SLT fits well with 2 of our 4 pseudo-branches:
2935 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2936 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2937 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2938 // This is accomplished by using a BNEZ with the result of the SLT.
2939 //
2940 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2941 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2942 // Because only BGE and BLE branch on equality, we can use the
2943 // AcceptsEquality variable to decide when to emit the BEQZ.
2944 // Note that the order of the SLT arguments doesn't change between
2945 // opposites.
2946 //
2947 // The same applies to the unsigned variants, except that SLTu is used
2948 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002949 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2950 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2951 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002952
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002953 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2954 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2955 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2956 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002957 return false;
2958}
2959
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002960bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2961 SmallVectorImpl<MCInst> &Instructions,
2962 const bool IsMips64, const bool Signed) {
2963 if (hasMips32r6()) {
2964 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2965 return false;
2966 }
2967
2968 warnIfNoMacro(IDLoc);
2969
2970 const MCOperand &RsRegOp = Inst.getOperand(0);
2971 assert(RsRegOp.isReg() && "expected register operand kind");
2972 unsigned RsReg = RsRegOp.getReg();
2973
2974 const MCOperand &RtRegOp = Inst.getOperand(1);
2975 assert(RtRegOp.isReg() && "expected register operand kind");
2976 unsigned RtReg = RtRegOp.getReg();
2977 unsigned DivOp;
2978 unsigned ZeroReg;
2979
2980 if (IsMips64) {
2981 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2982 ZeroReg = Mips::ZERO_64;
2983 } else {
2984 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2985 ZeroReg = Mips::ZERO;
2986 }
2987
2988 bool UseTraps = useTraps();
2989
2990 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2991 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2992 Warning(IDLoc, "dividing zero by zero");
2993 if (IsMips64) {
2994 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2995 if (UseTraps) {
2996 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2997 return false;
2998 }
2999
3000 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3001 return false;
3002 }
3003 } else {
3004 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3005 return false;
3006 }
3007 }
3008
3009 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3010 Warning(IDLoc, "division by zero");
3011 if (Signed) {
3012 if (UseTraps) {
3013 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3014 return false;
3015 }
3016
3017 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3018 return false;
3019 }
3020 }
3021
3022 // FIXME: The values for these two BranchTarget variables may be different in
3023 // micromips. These magic numbers need to be removed.
3024 unsigned BranchTargetNoTraps;
3025 unsigned BranchTarget;
3026
3027 if (UseTraps) {
3028 BranchTarget = IsMips64 ? 12 : 8;
3029 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3030 } else {
3031 BranchTarget = IsMips64 ? 20 : 16;
3032 BranchTargetNoTraps = 8;
3033 // Branch to the li instruction.
3034 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
3035 Instructions);
3036 }
3037
3038 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3039
3040 if (!UseTraps)
3041 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3042
3043 if (!Signed) {
3044 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3045 return false;
3046 }
3047
3048 unsigned ATReg = getATReg(IDLoc);
3049 if (!ATReg)
3050 return true;
3051
3052 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
3053 if (IsMips64) {
3054 // Branch to the mflo instruction.
3055 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3056 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
3057 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
3058 } else {
3059 // Branch to the mflo instruction.
3060 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3061 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
3062 }
3063
3064 if (UseTraps)
3065 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3066 else {
3067 // Branch to the mflo instruction.
3068 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3069 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3070 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3071 }
3072 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3073 return false;
3074}
3075
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003076bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
3077 SMLoc IDLoc,
3078 SmallVectorImpl<MCInst> &Instructions) {
3079
3080 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3081 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3082 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3083
3084 unsigned FirstReg = Inst.getOperand(0).getReg();
3085 unsigned SecondReg = Inst.getOperand(1).getReg();
3086 unsigned ThirdReg = Inst.getOperand(2).getReg();
3087
3088 if (hasMips1() && !hasMips2()) {
3089 unsigned ATReg = getATReg(IDLoc);
3090 if (!ATReg)
3091 return true;
3092 emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, Instructions);
3093 emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, Instructions);
3094 createNop(false, IDLoc, Instructions);
3095 emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, Instructions);
3096 emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, Instructions);
3097 emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, Instructions);
3098 createNop(false, IDLoc, Instructions);
3099 emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3100 : Mips::CVT_W_S,
3101 FirstReg, SecondReg, IDLoc, Instructions);
3102 emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, Instructions);
3103 createNop(false, IDLoc, Instructions);
3104 return false;
3105 }
3106
3107 emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3108 : Mips::TRUNC_W_S,
3109 FirstReg, SecondReg, IDLoc, Instructions);
3110
3111 return false;
3112}
3113
Daniel Sanders6394ee52015-10-15 14:52:58 +00003114bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3115 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003116 if (hasMips32r6() || hasMips64r6()) {
3117 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3118 return false;
3119 }
3120
3121 warnIfNoMacro(IDLoc);
3122
3123 const MCOperand &DstRegOp = Inst.getOperand(0);
3124 assert(DstRegOp.isReg() && "expected register operand kind");
3125
3126 const MCOperand &SrcRegOp = Inst.getOperand(1);
3127 assert(SrcRegOp.isReg() && "expected register operand kind");
3128
3129 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3130 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3131
3132 unsigned DstReg = DstRegOp.getReg();
3133 unsigned SrcReg = SrcRegOp.getReg();
3134 int64_t OffsetValue = OffsetImmOp.getImm();
3135
3136 // NOTE: We always need AT for ULHU, as it is always used as the source
3137 // register for one of the LBu's.
3138 unsigned ATReg = getATReg(IDLoc);
3139 if (!ATReg)
3140 return true;
3141
3142 // When the value of offset+1 does not fit in 16 bits, we have to load the
3143 // offset in AT, (D)ADDu the original source register (if there was one), and
3144 // then use AT as the source register for the 2 generated LBu's.
3145 bool LoadedOffsetInAT = false;
3146 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3147 LoadedOffsetInAT = true;
3148
3149 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003150 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003151 return true;
3152
3153 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3154 // because it will make our output more similar to GAS'. For example,
3155 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3156 // instead of just an "ori $1, $9, 32768".
3157 // NOTE: If there is no source register specified in the ULHU, the parser
3158 // will interpret it as $0.
3159 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3160 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3161 }
3162
3163 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3164 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3165 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3166
3167 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3168 if (isLittle()) {
3169 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3170 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3171 } else {
3172 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3173 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3174 }
3175
3176 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3177
Daniel Sanders6394ee52015-10-15 14:52:58 +00003178 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3179 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003180
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003181 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3182 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003183
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003184 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003185
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003186 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003187
3188 return false;
3189}
3190
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003191bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3192 SmallVectorImpl<MCInst> &Instructions) {
3193 if (hasMips32r6() || hasMips64r6()) {
3194 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3195 return false;
3196 }
3197
3198 const MCOperand &DstRegOp = Inst.getOperand(0);
3199 assert(DstRegOp.isReg() && "expected register operand kind");
3200
3201 const MCOperand &SrcRegOp = Inst.getOperand(1);
3202 assert(SrcRegOp.isReg() && "expected register operand kind");
3203
3204 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3205 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3206
3207 unsigned SrcReg = SrcRegOp.getReg();
3208 int64_t OffsetValue = OffsetImmOp.getImm();
3209 unsigned ATReg = 0;
3210
3211 // When the value of offset+3 does not fit in 16 bits, we have to load the
3212 // offset in AT, (D)ADDu the original source register (if there was one), and
3213 // then use AT as the source register for the generated LWL and LWR.
3214 bool LoadedOffsetInAT = false;
3215 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3216 ATReg = getATReg(IDLoc);
3217 if (!ATReg)
3218 return true;
3219 LoadedOffsetInAT = true;
3220
3221 warnIfNoMacro(IDLoc);
3222
3223 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003224 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003225 return true;
3226
3227 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3228 // because it will make our output more similar to GAS'. For example,
3229 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3230 // instead of just an "ori $1, $9, 32768".
3231 // NOTE: If there is no source register specified in the ULW, the parser
3232 // will interpret it as $0.
3233 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3234 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3235 }
3236
3237 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3238 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3239 if (isLittle()) {
3240 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3241 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3242 } else {
3243 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3244 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3245 }
3246
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003247 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3248 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003249
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003250 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3251 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003252
3253 return false;
3254}
3255
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003256bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3257 SmallVectorImpl<MCInst> &Instructions) {
3258
3259 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3260 assert (Inst.getOperand(0).isReg() &&
3261 Inst.getOperand(1).isReg() &&
3262 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3263
3264 unsigned ATReg = Mips::NoRegister;
3265 unsigned FinalDstReg = Mips::NoRegister;
3266 unsigned DstReg = Inst.getOperand(0).getReg();
3267 unsigned SrcReg = Inst.getOperand(1).getReg();
3268 int64_t ImmValue = Inst.getOperand(2).getImm();
3269
3270 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3271
3272 unsigned FinalOpcode = Inst.getOpcode();
3273
3274 if (DstReg == SrcReg) {
3275 ATReg = getATReg(Inst.getLoc());
3276 if (!ATReg)
3277 return true;
3278 FinalDstReg = DstReg;
3279 DstReg = ATReg;
3280 }
3281
3282 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3283 switch (FinalOpcode) {
3284 default:
3285 llvm_unreachable("unimplemented expansion");
3286 case (Mips::ADDi):
3287 FinalOpcode = Mips::ADD;
3288 break;
3289 case (Mips::ADDiu):
3290 FinalOpcode = Mips::ADDu;
3291 break;
3292 case (Mips::ANDi):
3293 FinalOpcode = Mips::AND;
3294 break;
3295 case (Mips::NORImm):
3296 FinalOpcode = Mips::NOR;
3297 break;
3298 case (Mips::ORi):
3299 FinalOpcode = Mips::OR;
3300 break;
3301 case (Mips::SLTi):
3302 FinalOpcode = Mips::SLT;
3303 break;
3304 case (Mips::SLTiu):
3305 FinalOpcode = Mips::SLTu;
3306 break;
3307 case (Mips::XORi):
3308 FinalOpcode = Mips::XOR;
3309 break;
3310 }
3311
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003312 if (FinalDstReg == Mips::NoRegister)
3313 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3314 else
3315 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3316 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003317 return false;
3318 }
3319 return true;
3320}
3321
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003322bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
3323 SmallVectorImpl<MCInst> &Instructions) {
3324 unsigned ATReg = Mips::NoRegister;
3325 unsigned DReg = Inst.getOperand(0).getReg();
3326 unsigned SReg = Inst.getOperand(1).getReg();
3327 unsigned TReg = Inst.getOperand(2).getReg();
3328 unsigned TmpReg = DReg;
3329
3330 unsigned FirstShift = Mips::NOP;
3331 unsigned SecondShift = Mips::NOP;
3332
3333 if (hasMips32r2()) {
3334
3335 if (DReg == SReg) {
3336 TmpReg = getATReg(Inst.getLoc());
3337 if (!TmpReg)
3338 return true;
3339 }
3340
3341 if (Inst.getOpcode() == Mips::ROL) {
3342 emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3343 emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3344 return false;
3345 }
3346
3347 if (Inst.getOpcode() == Mips::ROR) {
3348 emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3349 return false;
3350 }
3351
3352 return true;
3353 }
3354
3355 if (hasMips32()) {
3356
3357 switch (Inst.getOpcode()) {
3358 default:
3359 llvm_unreachable("unexpected instruction opcode");
3360 case Mips::ROL:
3361 FirstShift = Mips::SRLV;
3362 SecondShift = Mips::SLLV;
3363 break;
3364 case Mips::ROR:
3365 FirstShift = Mips::SLLV;
3366 SecondShift = Mips::SRLV;
3367 break;
3368 }
3369
3370 ATReg = getATReg(Inst.getLoc());
3371 if (!ATReg)
3372 return true;
3373
3374 emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3375 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3376 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3377 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3378
3379 return false;
3380 }
3381
3382 return true;
3383}
3384
3385bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
3386 SmallVectorImpl<MCInst> &Instructions) {
3387
3388 unsigned ATReg = Mips::NoRegister;
3389 unsigned DReg = Inst.getOperand(0).getReg();
3390 unsigned SReg = Inst.getOperand(1).getReg();
3391 int64_t ImmValue = Inst.getOperand(2).getImm();
3392
3393 unsigned FirstShift = Mips::NOP;
3394 unsigned SecondShift = Mips::NOP;
3395
3396 if (hasMips32r2()) {
3397
3398 if (Inst.getOpcode() == Mips::ROLImm) {
3399 uint64_t MaxShift = 32;
3400 uint64_t ShiftValue = ImmValue;
3401 if (ImmValue != 0)
3402 ShiftValue = MaxShift - ImmValue;
3403 emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3404 return false;
3405 }
3406
3407 if (Inst.getOpcode() == Mips::RORImm) {
3408 emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3409 return false;
3410 }
3411
3412 return true;
3413 }
3414
3415 if (hasMips32()) {
3416
3417 if (ImmValue == 0) {
3418 emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3419 return false;
3420 }
3421
3422 switch (Inst.getOpcode()) {
3423 default:
3424 llvm_unreachable("unexpected instruction opcode");
3425 case Mips::ROLImm:
3426 FirstShift = Mips::SLL;
3427 SecondShift = Mips::SRL;
3428 break;
3429 case Mips::RORImm:
3430 FirstShift = Mips::SRL;
3431 SecondShift = Mips::SLL;
3432 break;
3433 }
3434
3435 ATReg = getATReg(Inst.getLoc());
3436 if (!ATReg)
3437 return true;
3438
3439 emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3440 emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions);
3441 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3442
3443 return false;
3444 }
3445
3446 return true;
3447}
3448
3449bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
3450 SmallVectorImpl<MCInst> &Instructions) {
3451
3452 unsigned ATReg = Mips::NoRegister;
3453 unsigned DReg = Inst.getOperand(0).getReg();
3454 unsigned SReg = Inst.getOperand(1).getReg();
3455 unsigned TReg = Inst.getOperand(2).getReg();
3456 unsigned TmpReg = DReg;
3457
3458 unsigned FirstShift = Mips::NOP;
3459 unsigned SecondShift = Mips::NOP;
3460
3461 if (hasMips64r2()) {
3462
3463 if (TmpReg == SReg) {
3464 TmpReg = getATReg(Inst.getLoc());
3465 if (!TmpReg)
3466 return true;
3467 }
3468
3469 if (Inst.getOpcode() == Mips::DROL) {
3470 emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3471 emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3472 return false;
3473 }
3474
3475 if (Inst.getOpcode() == Mips::DROR) {
3476 emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3477 return false;
3478 }
3479
3480 return true;
3481 }
3482
3483 if (hasMips64()) {
3484
3485 switch (Inst.getOpcode()) {
3486 default:
3487 llvm_unreachable("unexpected instruction opcode");
3488 case Mips::DROL:
3489 FirstShift = Mips::DSRLV;
3490 SecondShift = Mips::DSLLV;
3491 break;
3492 case Mips::DROR:
3493 FirstShift = Mips::DSLLV;
3494 SecondShift = Mips::DSRLV;
3495 break;
3496 }
3497
3498 ATReg = getATReg(Inst.getLoc());
3499 if (!ATReg)
3500 return true;
3501
3502 emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3503 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3504 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3505 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3506
3507 return false;
3508 }
3509
3510 return true;
3511}
3512
3513bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
3514 SmallVectorImpl<MCInst> &Instructions) {
3515
3516 unsigned ATReg = Mips::NoRegister;
3517 unsigned DReg = Inst.getOperand(0).getReg();
3518 unsigned SReg = Inst.getOperand(1).getReg();
3519 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3520
3521 unsigned FirstShift = Mips::NOP;
3522 unsigned SecondShift = Mips::NOP;
3523
3524 MCInst TmpInst;
3525
3526 if (hasMips64r2()) {
3527
3528 unsigned FinalOpcode = Mips::NOP;
3529 if (ImmValue == 0)
3530 FinalOpcode = Mips::DROTR;
3531 else if (ImmValue % 32 == 0)
3532 FinalOpcode = Mips::DROTR32;
3533 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3534 if (Inst.getOpcode() == Mips::DROLImm)
3535 FinalOpcode = Mips::DROTR32;
3536 else
3537 FinalOpcode = Mips::DROTR;
3538 } else if (ImmValue >= 33) {
3539 if (Inst.getOpcode() == Mips::DROLImm)
3540 FinalOpcode = Mips::DROTR;
3541 else
3542 FinalOpcode = Mips::DROTR32;
3543 }
3544
3545 uint64_t ShiftValue = ImmValue % 32;
3546 if (Inst.getOpcode() == Mips::DROLImm)
3547 ShiftValue = (32 - ImmValue % 32) % 32;
3548
3549 emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3550
3551 return false;
3552 }
3553
3554 if (hasMips64()) {
3555
3556 if (ImmValue == 0) {
3557 emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3558 return false;
3559 }
3560
3561 switch (Inst.getOpcode()) {
3562 default:
3563 llvm_unreachable("unexpected instruction opcode");
3564 case Mips::DROLImm:
3565 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3566 FirstShift = Mips::DSLL;
3567 SecondShift = Mips::DSRL32;
3568 }
3569 if (ImmValue == 32) {
3570 FirstShift = Mips::DSLL32;
3571 SecondShift = Mips::DSRL32;
3572 }
3573 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3574 FirstShift = Mips::DSLL32;
3575 SecondShift = Mips::DSRL;
3576 }
3577 break;
3578 case Mips::DRORImm:
3579 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3580 FirstShift = Mips::DSRL;
3581 SecondShift = Mips::DSLL32;
3582 }
3583 if (ImmValue == 32) {
3584 FirstShift = Mips::DSRL32;
3585 SecondShift = Mips::DSLL32;
3586 }
3587 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3588 FirstShift = Mips::DSRL32;
3589 SecondShift = Mips::DSLL;
3590 }
3591 break;
3592 }
3593
3594 ATReg = getATReg(Inst.getLoc());
3595 if (!ATReg)
3596 return true;
3597
3598 emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions);
3599 emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions);
3600 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3601
3602 return false;
3603 }
3604
3605 return true;
3606}
3607
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003608bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc,
3609 SmallVectorImpl<MCInst> &Instructions) {
3610
3611 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3612 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3613
3614 emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, Instructions);
3615 if (FirstRegOp != SecondRegOp)
3616 emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, Instructions);
3617 else
3618 createNop(false, IDLoc, Instructions);
3619 emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, Instructions);
3620
3621 return false;
3622}
3623
Toma Tabacu234482a2015-03-16 12:03:39 +00003624void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3625 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003626 if (hasShortDelaySlot)
3627 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3628 else
3629 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003630}
3631
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003632void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003633 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003634 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003635 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3636 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003637}
3638
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003639void MipsAsmParser::createCpRestoreMemOp(
3640 bool IsLoad, int StackOffset, SMLoc IDLoc,
3641 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003642 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003643 if (!isInt<16>(StackOffset)) {
3644 MCInst MemInst;
3645 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3646 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3647 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3648 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003649 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003650 return;
3651 }
3652
3653 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3654 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003655}
3656
Matheus Almeida595fcab2014-06-11 15:05:56 +00003657unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3658 // As described by the Mips32r2 spec, the registers Rd and Rs for
3659 // jalr.hb must be different.
3660 unsigned Opcode = Inst.getOpcode();
3661
3662 if (Opcode == Mips::JALR_HB &&
3663 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3664 return Match_RequiresDifferentSrcAndDst;
3665
3666 return Match_Success;
3667}
3668
Daniel Sanders52da7af2015-11-06 12:11:03 +00003669static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3670 uint64_t ErrorInfo) {
3671 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3672 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3673 if (ErrorLoc == SMLoc())
3674 return Loc;
3675 return ErrorLoc;
3676 }
3677 return Loc;
3678}
3679
David Blaikie960ea3f2014-06-08 16:18:35 +00003680bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3681 OperandVector &Operands,
3682 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003683 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003684 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003685
Jack Carterb4dbc172012-09-05 23:34:03 +00003686 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003687 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003688 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003689 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003690
3691 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003692 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003693 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003694 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003695 for (unsigned i = 0; i < Instructions.size(); i++)
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003696 Out.EmitInstruction(Instructions[i], getSTI());
Jack Carterb4dbc172012-09-05 23:34:03 +00003697 return false;
3698 }
3699 case Match_MissingFeature:
3700 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3701 return true;
3702 case Match_InvalidOperand: {
3703 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003704 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003705 if (ErrorInfo >= Operands.size())
3706 return Error(IDLoc, "too few operands for instruction");
3707
Daniel Sanders52da7af2015-11-06 12:11:03 +00003708 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003709 if (ErrorLoc == SMLoc())
3710 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003711 }
3712
3713 return Error(ErrorLoc, "invalid operand for instruction");
3714 }
3715 case Match_MnemonicFail:
3716 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003717 case Match_RequiresDifferentSrcAndDst:
3718 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003719 case Match_Immz:
3720 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003721 case Match_UImm1_0:
3722 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3723 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003724 case Match_UImm2_0:
3725 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3726 "expected 2-bit unsigned immediate");
3727 case Match_UImm2_1:
3728 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3729 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003730 case Match_UImm3_0:
3731 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3732 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003733 case Match_UImm4_0:
3734 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3735 "expected 4-bit unsigned immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003736 case Match_UImm5_0:
3737 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3738 "expected 5-bit unsigned immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003739 case Match_UImm5_1:
3740 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3741 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003742 case Match_UImm5_32:
3743 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3744 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003745 case Match_UImm5_33:
3746 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3747 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003748 case Match_UImm5_0_Report_UImm6:
3749 // This is used on UImm5 operands that have a corresponding UImm5_32
3750 // operand to avoid confusing the user.
3751 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3752 "expected 6-bit unsigned immediate");
3753 case Match_UImm5_Lsl2:
3754 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3755 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003756 case Match_UImmRange2_64:
3757 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3758 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003759 case Match_UImm6_0:
3760 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3761 "expected 6-bit unsigned immediate");
Zlatko Buljan252cca52015-12-18 08:59:37 +00003762 case Match_SImm6:
3763 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3764 "expected 6-bit signed immediate");
3765 case Match_UImm7_0:
3766 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3767 "expected 7-bit unsigned immediate");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003768 case Match_UImm8_0:
3769 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3770 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003771 case Match_UImm10_0:
3772 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3773 "expected 10-bit unsigned immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003774 case Match_UImm16:
3775 case Match_UImm16_Relaxed:
3776 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3777 "expected 16-bit unsigned immediate");
Jack Carterb4dbc172012-09-05 23:34:03 +00003778 }
Craig Topper589ceee2015-01-03 08:16:34 +00003779
3780 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003781}
3782
Toma Tabacud9d344b2015-04-27 14:05:04 +00003783void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3784 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3785 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3786 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003787}
3788
Toma Tabacu81496c12015-05-20 08:54:45 +00003789void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3790 if (!AssemblerOptions.back()->isMacro())
3791 Warning(Loc, "macro instruction expanded into multiple instructions");
3792}
3793
Daniel Sandersef638fe2014-10-03 15:37:37 +00003794void
3795MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3796 SMRange Range, bool ShowColors) {
3797 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003798 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003799 ShowColors);
3800}
3801
Jack Carter1ac53222013-02-20 23:11:17 +00003802int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003803 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003804
Vladimir Medic4c299852013-11-06 11:27:05 +00003805 CC = StringSwitch<unsigned>(Name)
3806 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003807 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003808 .Case("a0", 4)
3809 .Case("a1", 5)
3810 .Case("a2", 6)
3811 .Case("a3", 7)
3812 .Case("v0", 2)
3813 .Case("v1", 3)
3814 .Case("s0", 16)
3815 .Case("s1", 17)
3816 .Case("s2", 18)
3817 .Case("s3", 19)
3818 .Case("s4", 20)
3819 .Case("s5", 21)
3820 .Case("s6", 22)
3821 .Case("s7", 23)
3822 .Case("k0", 26)
3823 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003824 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003825 .Case("sp", 29)
3826 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003827 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003828 .Case("ra", 31)
3829 .Case("t0", 8)
3830 .Case("t1", 9)
3831 .Case("t2", 10)
3832 .Case("t3", 11)
3833 .Case("t4", 12)
3834 .Case("t5", 13)
3835 .Case("t6", 14)
3836 .Case("t7", 15)
3837 .Case("t8", 24)
3838 .Case("t9", 25)
3839 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003840
Toma Tabacufda445c2014-09-15 15:33:01 +00003841 if (!(isABI_N32() || isABI_N64()))
3842 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003843
Daniel Sandersef638fe2014-10-03 15:37:37 +00003844 if (12 <= CC && CC <= 15) {
3845 // Name is one of t4-t7
3846 AsmToken RegTok = getLexer().peekTok();
3847 SMRange RegRange = RegTok.getLocRange();
3848
3849 StringRef FixedName = StringSwitch<StringRef>(Name)
3850 .Case("t4", "t0")
3851 .Case("t5", "t1")
3852 .Case("t6", "t2")
3853 .Case("t7", "t3")
3854 .Default("");
3855 assert(FixedName != "" && "Register name is not one of t4-t7.");
3856
3857 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3858 "Did you mean $" + FixedName + "?", RegRange);
3859 }
3860
Toma Tabacufda445c2014-09-15 15:33:01 +00003861 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3862 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3863 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3864 if (8 <= CC && CC <= 11)
3865 CC += 4;
3866
3867 if (CC == -1)
3868 CC = StringSwitch<unsigned>(Name)
3869 .Case("a4", 8)
3870 .Case("a5", 9)
3871 .Case("a6", 10)
3872 .Case("a7", 11)
3873 .Case("kt0", 26)
3874 .Case("kt1", 27)
3875 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003876
3877 return CC;
3878}
Jack Carterd0bd6422013-04-18 00:41:53 +00003879
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003880int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3881 int CC;
3882
3883 CC = StringSwitch<unsigned>(Name)
3884 .Case("hwr_cpunum", 0)
3885 .Case("hwr_synci_step", 1)
3886 .Case("hwr_cc", 2)
3887 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003888 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003889 .Default(-1);
3890
3891 return CC;
3892}
3893
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003894int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003895
Jack Cartera63b16a2012-09-07 00:23:42 +00003896 if (Name[0] == 'f') {
3897 StringRef NumString = Name.substr(1);
3898 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003899 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003900 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003901 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003902 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003903 return IntVal;
3904 }
3905 return -1;
3906}
Jack Cartera63b16a2012-09-07 00:23:42 +00003907
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003908int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3909
3910 if (Name.startswith("fcc")) {
3911 StringRef NumString = Name.substr(3);
3912 unsigned IntVal;
3913 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003914 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003915 if (IntVal > 7) // There are only 8 fcc registers.
3916 return -1;
3917 return IntVal;
3918 }
3919 return -1;
3920}
3921
3922int MipsAsmParser::matchACRegisterName(StringRef Name) {
3923
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003924 if (Name.startswith("ac")) {
3925 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003926 unsigned IntVal;
3927 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003928 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003929 if (IntVal > 3) // There are only 3 acc registers.
3930 return -1;
3931 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003932 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003933 return -1;
3934}
Jack Carterd0bd6422013-04-18 00:41:53 +00003935
Jack Carter5dc8ac92013-09-25 23:50:44 +00003936int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3937 unsigned IntVal;
3938
3939 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3940 return -1;
3941
3942 if (IntVal > 31)
3943 return -1;
3944
3945 return IntVal;
3946}
3947
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003948int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3949 int CC;
3950
3951 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003952 .Case("msair", 0)
3953 .Case("msacsr", 1)
3954 .Case("msaaccess", 2)
3955 .Case("msasave", 3)
3956 .Case("msamodify", 4)
3957 .Case("msarequest", 5)
3958 .Case("msamap", 6)
3959 .Case("msaunmap", 7)
3960 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003961
3962 return CC;
3963}
3964
Toma Tabacu89a712b2015-04-15 10:48:56 +00003965unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003966 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003967 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003968 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003969 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003970 return 0;
3971 }
3972 unsigned AT = getReg(
3973 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003974 return AT;
3975}
Jack Carter0b744b32012-10-04 02:29:46 +00003976
Jack Carterd0bd6422013-04-18 00:41:53 +00003977unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003978 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003979}
3980
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003981unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003982 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003983 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003984}
3985
Jack Carter873c7242013-01-12 01:03:14 +00003986int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003987 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003988 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003989 return -1;
3990
Jack Carter873c7242013-01-12 01:03:14 +00003991 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003992}
3993
Toma Tabacu13964452014-09-04 13:23:44 +00003994bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003995 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003996 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003997
Jack Carter30a59822012-10-04 04:03:53 +00003998 // Check if the current operand has a custom associated parser, if so, try to
3999 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004000 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4001 if (ResTy == MatchOperand_Success)
4002 return false;
4003 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4004 // there was a match, but an error occurred, in which case, just return that
4005 // the operand parsing failed.
4006 if (ResTy == MatchOperand_ParseFail)
4007 return true;
4008
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004009 DEBUG(dbgs() << ".. Generic Parser\n");
4010
Jack Carterb4dbc172012-09-05 23:34:03 +00004011 switch (getLexer().getKind()) {
4012 default:
4013 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4014 return true;
4015 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004016 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004017 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004018
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004019 // Almost all registers have been parsed by custom parsers. There is only
4020 // one exception to this. $zero (and it's alias $0) will reach this point
4021 // for div, divu, and similar instructions because it is not an operand
4022 // to the instruction definition but an explicit register. Special case
4023 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004024 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004025 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004026
Jack Carterd0bd6422013-04-18 00:41:53 +00004027 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004028 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004029 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004030 return true;
4031
Jack Carter873c7242013-01-12 01:03:14 +00004032 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004033 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004034 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004035 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004036 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004037
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004038 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004039 return false;
4040 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004041 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004042 case AsmToken::LParen:
4043 case AsmToken::Minus:
4044 case AsmToken::Plus:
4045 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004046 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004047 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004048 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004049 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004050 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004051 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004052 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004053 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004054 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004055 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004056 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004057 return true;
4058
Jack Carter873c7242013-01-12 01:03:14 +00004059 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4060
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004061 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004062 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004063 } // case AsmToken::Percent
4064 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004065 return true;
4066}
4067
Vladimir Medic4c299852013-11-06 11:27:05 +00004068const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004069 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004070 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00004071 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004072 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00004073 // It's a constant, evaluate reloc value.
4074 int16_t Val;
4075 switch (getVariantKind(RelocStr)) {
4076 case MCSymbolRefExpr::VK_Mips_ABS_LO:
4077 // Get the 1st 16-bits.
4078 Val = MCE->getValue() & 0xffff;
4079 break;
4080 case MCSymbolRefExpr::VK_Mips_ABS_HI:
Simon Atanasyan2fc1e3b2016-02-09 22:31:49 +00004081 case MCSymbolRefExpr::VK_Mips_GOT:
Sasa Stankovic06c47802014-04-03 10:37:45 +00004082 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
4083 // 16 bits being negative.
4084 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
4085 break;
4086 case MCSymbolRefExpr::VK_Mips_HIGHER:
4087 // Get the 3rd 16-bits.
4088 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
4089 break;
4090 case MCSymbolRefExpr::VK_Mips_HIGHEST:
4091 // Get the 4th 16-bits.
4092 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
4093 break;
4094 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00004095 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00004096 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004097 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004098 }
4099
Jack Carterb5cf5902013-04-17 00:18:04 +00004100 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004101 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00004102 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00004103 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004104 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004105 return Res;
4106 }
4107
4108 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00004109 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
4110
Sasa Stankovic06c47802014-04-03 10:37:45 +00004111 // Try to create target expression.
4112 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00004113 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004114
Jack Carterd0bd6422013-04-18 00:41:53 +00004115 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
4116 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004117 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004118 return Res;
4119 }
4120
4121 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004122 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004123 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00004124 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00004125 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004126 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004127 return Expr;
4128}
4129
4130bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4131
4132 switch (Expr->getKind()) {
4133 case MCExpr::Constant:
4134 return true;
4135 case MCExpr::SymbolRef:
4136 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4137 case MCExpr::Binary:
4138 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4139 if (!isEvaluated(BE->getLHS()))
4140 return false;
4141 return isEvaluated(BE->getRHS());
4142 }
4143 case MCExpr::Unary:
4144 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004145 case MCExpr::Target:
4146 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004147 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004148 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004149}
Jack Carterd0bd6422013-04-18 00:41:53 +00004150
Jack Carterb5cf5902013-04-17 00:18:04 +00004151bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004152 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004153 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004154 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004155 if (Tok.isNot(AsmToken::Identifier))
4156 return true;
4157
Yaron Keren075759a2015-03-30 15:42:36 +00004158 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004159
Jack Carterd0bd6422013-04-18 00:41:53 +00004160 Parser.Lex(); // Eat the identifier.
4161 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004162 const MCExpr *IdVal;
4163 SMLoc EndLoc;
4164
4165 if (getLexer().getKind() == AsmToken::LParen) {
4166 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004167 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004168 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004169 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004170 const AsmToken &nextTok = Parser.getTok();
4171 if (nextTok.isNot(AsmToken::Identifier))
4172 return true;
4173 Str += "(%";
4174 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004175 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004176 if (getLexer().getKind() != AsmToken::LParen)
4177 return true;
4178 } else
4179 break;
4180 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004181 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004182 return true;
4183
4184 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004185 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004186
4187 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004188 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004189
Jack Carterd0bd6422013-04-18 00:41:53 +00004190 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004191 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004192}
4193
Jack Carterb4dbc172012-09-05 23:34:03 +00004194bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4195 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004196 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004197 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004198 if (ResTy == MatchOperand_Success) {
4199 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004200 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004201 StartLoc = Operand.getStartLoc();
4202 EndLoc = Operand.getEndLoc();
4203
4204 // AFAIK, we only support numeric registers and named GPR's in CFI
4205 // directives.
4206 // Don't worry about eating tokens before failing. Using an unrecognised
4207 // register is a parse error.
4208 if (Operand.isGPRAsmReg()) {
4209 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004210 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004211 }
4212
4213 return (RegNo == (unsigned)-1);
4214 }
4215
4216 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004217 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004218}
4219
Jack Carterb5cf5902013-04-17 00:18:04 +00004220bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004221 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004222 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004223 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004224 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004225
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004226 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004227 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004228 ++NumOfLParen;
4229 }
Jack Carter873c7242013-01-12 01:03:14 +00004230
Jack Carterd0bd6422013-04-18 00:41:53 +00004231 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004232 default:
4233 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004234 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004235 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004236 case AsmToken::Integer:
4237 case AsmToken::Minus:
4238 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004239 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004240 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004241 else
4242 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004243 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004244 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004245 break;
Jack Carter873c7242013-01-12 01:03:14 +00004246 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004247 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004248 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004249 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004250}
4251
David Blaikie960ea3f2014-06-08 16:18:35 +00004252MipsAsmParser::OperandMatchResultTy
4253MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004254 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004255 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004256 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004257 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004258 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004259 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004260 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004261 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004262
Jack Carterb5cf5902013-04-17 00:18:04 +00004263 if (getLexer().getKind() == AsmToken::LParen) {
4264 Parser.Lex();
4265 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004266 }
4267
Jack Carterb5cf5902013-04-17 00:18:04 +00004268 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004269 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004270 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004271
Jack Carterd0bd6422013-04-18 00:41:53 +00004272 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004273 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004274 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004275 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004276 SMLoc E =
4277 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004278 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004279 return MatchOperand_Success;
4280 }
4281 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004282 SMLoc E =
4283 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004284
Jack Carterd0bd6422013-04-18 00:41:53 +00004285 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004286 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004287 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004288 S, E, *this);
4289 Operands.push_back(
4290 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004291 return MatchOperand_Success;
4292 }
4293 Error(Parser.getTok().getLoc(), "'(' expected");
4294 return MatchOperand_ParseFail;
4295 }
4296
Jack Carterd0bd6422013-04-18 00:41:53 +00004297 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004298 }
4299
Toma Tabacu13964452014-09-04 13:23:44 +00004300 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004301 if (Res != MatchOperand_Success)
4302 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004303
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004304 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004305 Error(Parser.getTok().getLoc(), "')' expected");
4306 return MatchOperand_ParseFail;
4307 }
4308
Jack Carter873c7242013-01-12 01:03:14 +00004309 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4310
Jack Carterd0bd6422013-04-18 00:41:53 +00004311 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004312
Craig Topper062a2ba2014-04-25 05:30:21 +00004313 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004314 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004315
Jack Carterd0bd6422013-04-18 00:41:53 +00004316 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004317 std::unique_ptr<MipsOperand> op(
4318 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004319 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004320 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004321 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004322 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004323 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4324 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004325 if (IdVal->evaluateAsAbsolute(Imm))
4326 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004327 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004328 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004329 getContext());
4330 }
4331
David Blaikie960ea3f2014-06-08 16:18:35 +00004332 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004333 return MatchOperand_Success;
4334}
4335
David Blaikie960ea3f2014-06-08 16:18:35 +00004336bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004337 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004338 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004339 if (Sym) {
4340 SMLoc S = Parser.getTok().getLoc();
4341 const MCExpr *Expr;
4342 if (Sym->isVariable())
4343 Expr = Sym->getVariableValue();
4344 else
4345 return false;
4346 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004347 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004348 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004349 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004350 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004351 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004352 if (ResTy == MatchOperand_Success) {
4353 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004354 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004355 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004356 llvm_unreachable("Should never ParseFail");
4357 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004358 }
4359 } else if (Expr->getKind() == MCExpr::Constant) {
4360 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004361 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004362 Operands.push_back(
4363 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004364 return true;
4365 }
4366 }
4367 return false;
4368}
Jack Carterd0bd6422013-04-18 00:41:53 +00004369
Jack Carter873c7242013-01-12 01:03:14 +00004370MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004371MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004372 StringRef Identifier,
4373 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004374 int Index = matchCPURegisterName(Identifier);
4375 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004376 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004377 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4378 return MatchOperand_Success;
4379 }
4380
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004381 Index = matchHWRegsRegisterName(Identifier);
4382 if (Index != -1) {
4383 Operands.push_back(MipsOperand::createHWRegsReg(
4384 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4385 return MatchOperand_Success;
4386 }
4387
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004388 Index = matchFPURegisterName(Identifier);
4389 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004390 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004391 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4392 return MatchOperand_Success;
4393 }
4394
4395 Index = matchFCCRegisterName(Identifier);
4396 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004397 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004398 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4399 return MatchOperand_Success;
4400 }
4401
4402 Index = matchACRegisterName(Identifier);
4403 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004404 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004405 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4406 return MatchOperand_Success;
4407 }
4408
4409 Index = matchMSA128RegisterName(Identifier);
4410 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004411 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004412 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4413 return MatchOperand_Success;
4414 }
4415
4416 Index = matchMSA128CtrlRegisterName(Identifier);
4417 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004418 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004419 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4420 return MatchOperand_Success;
4421 }
4422
4423 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004424}
4425
4426MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004427MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004428 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004429 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004430
4431 if (Token.is(AsmToken::Identifier)) {
4432 DEBUG(dbgs() << ".. identifier\n");
4433 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004434 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004435 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004436 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004437 } else if (Token.is(AsmToken::Integer)) {
4438 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004439 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004440 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4441 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004442 return MatchOperand_Success;
4443 }
4444
4445 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4446
4447 return MatchOperand_NoMatch;
4448}
4449
David Blaikie960ea3f2014-06-08 16:18:35 +00004450MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004451MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004452 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004453 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004454
4455 auto Token = Parser.getTok();
4456
4457 SMLoc S = Token.getLoc();
4458
4459 if (Token.isNot(AsmToken::Dollar)) {
4460 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4461 if (Token.is(AsmToken::Identifier)) {
4462 if (searchSymbolAlias(Operands))
4463 return MatchOperand_Success;
4464 }
4465 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4466 return MatchOperand_NoMatch;
4467 }
4468 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004469
Toma Tabacu13964452014-09-04 13:23:44 +00004470 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004471 if (ResTy == MatchOperand_Success) {
4472 Parser.Lex(); // $
4473 Parser.Lex(); // identifier
4474 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004475 return ResTy;
4476}
4477
4478MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004479MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004480 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004481 switch (getLexer().getKind()) {
4482 default:
4483 return MatchOperand_NoMatch;
4484 case AsmToken::LParen:
4485 case AsmToken::Minus:
4486 case AsmToken::Plus:
4487 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004488 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004489 case AsmToken::String:
4490 break;
4491 }
4492
4493 const MCExpr *IdVal;
4494 SMLoc S = Parser.getTok().getLoc();
4495 if (getParser().parseExpression(IdVal))
4496 return MatchOperand_ParseFail;
4497
4498 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4499 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4500 return MatchOperand_Success;
4501}
4502
David Blaikie960ea3f2014-06-08 16:18:35 +00004503MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004504MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004505 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004506 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004507
4508 SMLoc S = getLexer().getLoc();
4509
4510 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004511 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004512 if (ResTy != MatchOperand_NoMatch)
4513 return ResTy;
4514
Daniel Sanders315386c2014-04-01 10:40:14 +00004515 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004516 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004517 if (ResTy != MatchOperand_NoMatch)
4518 return ResTy;
4519
Daniel Sandersffd84362014-04-01 10:41:48 +00004520 const MCExpr *Expr = nullptr;
4521 if (Parser.parseExpression(Expr)) {
4522 // We have no way of knowing if a symbol was consumed so we must ParseFail
4523 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004524 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004525 Operands.push_back(
4526 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004527 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004528}
4529
Vladimir Medic2b953d02013-10-01 09:48:56 +00004530MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004531MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004532 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004533 const MCExpr *IdVal;
4534 // If the first token is '$' we may have register operand.
4535 if (Parser.getTok().is(AsmToken::Dollar))
4536 return MatchOperand_NoMatch;
4537 SMLoc S = Parser.getTok().getLoc();
4538 if (getParser().parseExpression(IdVal))
4539 return MatchOperand_ParseFail;
4540 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004541 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004542 int64_t Val = MCE->getValue();
4543 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4544 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004545 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004546 return MatchOperand_Success;
4547}
4548
Matheus Almeida779c5932013-11-18 12:32:49 +00004549MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004550MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004551 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004552 switch (getLexer().getKind()) {
4553 default:
4554 return MatchOperand_NoMatch;
4555 case AsmToken::LParen:
4556 case AsmToken::Plus:
4557 case AsmToken::Minus:
4558 case AsmToken::Integer:
4559 break;
4560 }
4561
4562 const MCExpr *Expr;
4563 SMLoc S = Parser.getTok().getLoc();
4564
4565 if (getParser().parseExpression(Expr))
4566 return MatchOperand_ParseFail;
4567
4568 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004569 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004570 Error(S, "expected immediate value");
4571 return MatchOperand_ParseFail;
4572 }
4573
4574 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4575 // and because the CPU always adds one to the immediate field, the allowed
4576 // range becomes 1..4. We'll only check the range here and will deal
4577 // with the addition/subtraction when actually decoding/encoding
4578 // the instruction.
4579 if (Val < 1 || Val > 4) {
4580 Error(S, "immediate not in range (1..4)");
4581 return MatchOperand_ParseFail;
4582 }
4583
Jack Carter3b2c96e2014-01-22 23:31:38 +00004584 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004585 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004586 return MatchOperand_Success;
4587}
4588
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004589MipsAsmParser::OperandMatchResultTy
4590MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4591 MCAsmParser &Parser = getParser();
4592 SmallVector<unsigned, 10> Regs;
4593 unsigned RegNo;
4594 unsigned PrevReg = Mips::NoRegister;
4595 bool RegRange = false;
4596 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4597
4598 if (Parser.getTok().isNot(AsmToken::Dollar))
4599 return MatchOperand_ParseFail;
4600
4601 SMLoc S = Parser.getTok().getLoc();
4602 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4603 SMLoc E = getLexer().getLoc();
4604 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4605 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4606 if (RegRange) {
4607 // Remove last register operand because registers from register range
4608 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004609 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4610 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004611 Regs.push_back(RegNo);
4612 } else {
4613 unsigned TmpReg = PrevReg + 1;
4614 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004615 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4616 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4617 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004618 Error(E, "invalid register operand");
4619 return MatchOperand_ParseFail;
4620 }
4621
4622 PrevReg = TmpReg;
4623 Regs.push_back(TmpReg++);
4624 }
4625 }
4626
4627 RegRange = false;
4628 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004629 if ((PrevReg == Mips::NoRegister) &&
4630 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4631 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004632 Error(E, "$16 or $31 expected");
4633 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004634 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4635 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4636 !isGP64bit()) ||
4637 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4638 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4639 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004640 Error(E, "invalid register operand");
4641 return MatchOperand_ParseFail;
4642 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004643 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4644 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4645 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004646 Error(E, "consecutive register numbers expected");
4647 return MatchOperand_ParseFail;
4648 }
4649
4650 Regs.push_back(RegNo);
4651 }
4652
4653 if (Parser.getTok().is(AsmToken::Minus))
4654 RegRange = true;
4655
4656 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4657 !Parser.getTok().isNot(AsmToken::Comma)) {
4658 Error(E, "',' or '-' expected");
4659 return MatchOperand_ParseFail;
4660 }
4661
4662 Lex(); // Consume comma or minus
4663 if (Parser.getTok().isNot(AsmToken::Dollar))
4664 break;
4665
4666 PrevReg = RegNo;
4667 }
4668
4669 SMLoc E = Parser.getTok().getLoc();
4670 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4671 parseMemOperand(Operands);
4672 return MatchOperand_Success;
4673}
4674
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004675MipsAsmParser::OperandMatchResultTy
4676MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4677 MCAsmParser &Parser = getParser();
4678
4679 SMLoc S = Parser.getTok().getLoc();
4680 if (parseAnyRegister(Operands) != MatchOperand_Success)
4681 return MatchOperand_ParseFail;
4682
4683 SMLoc E = Parser.getTok().getLoc();
4684 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4685 unsigned Reg = Op.getGPR32Reg();
4686 Operands.pop_back();
4687 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4688 return MatchOperand_Success;
4689}
4690
Zoran Jovanovic41688672015-02-10 16:36:20 +00004691MipsAsmParser::OperandMatchResultTy
4692MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4693 MCAsmParser &Parser = getParser();
4694 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4695 SmallVector<unsigned, 10> Regs;
4696
4697 if (Parser.getTok().isNot(AsmToken::Dollar))
4698 return MatchOperand_ParseFail;
4699
4700 SMLoc S = Parser.getTok().getLoc();
4701
4702 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4703 return MatchOperand_ParseFail;
4704
4705 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4706 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4707 Regs.push_back(RegNo);
4708
4709 SMLoc E = Parser.getTok().getLoc();
4710 if (Parser.getTok().isNot(AsmToken::Comma)) {
4711 Error(E, "',' expected");
4712 return MatchOperand_ParseFail;
4713 }
4714
4715 // Remove comma.
4716 Parser.Lex();
4717
4718 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4719 return MatchOperand_ParseFail;
4720
4721 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4722 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4723 Regs.push_back(RegNo);
4724
4725 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4726
4727 return MatchOperand_Success;
4728}
4729
Jack Carterdc1e35d2012-09-06 20:00:02 +00004730MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4731
Vladimir Medic4c299852013-11-06 11:27:05 +00004732 MCSymbolRefExpr::VariantKind VK =
4733 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4734 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4735 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4736 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4737 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4738 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4739 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4740 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4741 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4742 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4743 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4744 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4745 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4746 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4747 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4748 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4749 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4750 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004751 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4752 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4753 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4754 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4755 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4756 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004757 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4758 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004759 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004760
Matheus Almeida2852af82014-04-22 10:15:54 +00004761 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004762
Jack Carterdc1e35d2012-09-06 20:00:02 +00004763 return VK;
4764}
Jack Cartera63b16a2012-09-07 00:23:42 +00004765
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004766/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4767/// either this.
4768/// ::= '(', register, ')'
4769/// handle it before we iterate so we don't get tripped up by the lack of
4770/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004771bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004772 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004773 if (getLexer().is(AsmToken::LParen)) {
4774 Operands.push_back(
4775 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4776 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004777 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004778 SMLoc Loc = getLexer().getLoc();
4779 Parser.eatToEndOfStatement();
4780 return Error(Loc, "unexpected token in argument list");
4781 }
4782 if (Parser.getTok().isNot(AsmToken::RParen)) {
4783 SMLoc Loc = getLexer().getLoc();
4784 Parser.eatToEndOfStatement();
4785 return Error(Loc, "unexpected token, expected ')'");
4786 }
4787 Operands.push_back(
4788 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4789 Parser.Lex();
4790 }
4791 return false;
4792}
4793
4794/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4795/// either one of these.
4796/// ::= '[', register, ']'
4797/// ::= '[', integer, ']'
4798/// handle it before we iterate so we don't get tripped up by the lack of
4799/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004800bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004801 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004802 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004803 if (getLexer().is(AsmToken::LBrac)) {
4804 Operands.push_back(
4805 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4806 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004807 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004808 SMLoc Loc = getLexer().getLoc();
4809 Parser.eatToEndOfStatement();
4810 return Error(Loc, "unexpected token in argument list");
4811 }
4812 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4813 SMLoc Loc = getLexer().getLoc();
4814 Parser.eatToEndOfStatement();
4815 return Error(Loc, "unexpected token, expected ']'");
4816 }
4817 Operands.push_back(
4818 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4819 Parser.Lex();
4820 }
4821 return false;
4822}
4823
David Blaikie960ea3f2014-06-08 16:18:35 +00004824bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4825 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004826 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004827 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004828
4829 // We have reached first instruction, module directive are now forbidden.
4830 getTargetStreamer().forbidModuleDirective();
4831
Vladimir Medic74593e62013-07-17 15:00:42 +00004832 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004833 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004834 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004835 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004836 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004837 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004838 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004839
4840 // Read the remaining operands.
4841 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4842 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004843 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004844 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004845 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004846 return Error(Loc, "unexpected token in argument list");
4847 }
Toma Tabacu13964452014-09-04 13:23:44 +00004848 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004849 return true;
4850 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004851
Jack Carterd0bd6422013-04-18 00:41:53 +00004852 while (getLexer().is(AsmToken::Comma)) {
4853 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004854 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004855 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004856 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004857 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004858 return Error(Loc, "unexpected token in argument list");
4859 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004860 // Parse bracket and parenthesis suffixes before we iterate
4861 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004862 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004863 return true;
4864 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004865 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004866 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004867 }
4868 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004869 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4870 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004871 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004872 return Error(Loc, "unexpected token in argument list");
4873 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004874 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004875 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004876}
4877
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004878bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004879 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004880 SMLoc Loc = getLexer().getLoc();
4881 Parser.eatToEndOfStatement();
4882 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004883}
4884
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004885bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004886 return Error(Loc, ErrorMsg);
4887}
4888
Jack Carter0b744b32012-10-04 02:29:46 +00004889bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004890 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004891 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004892
4893 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004894 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004895
4896 Parser.Lex(); // Eat "noat".
4897
Jack Carterd0bd6422013-04-18 00:41:53 +00004898 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004899 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004900 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004901 return false;
4902 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004903
4904 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004905 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004906 return false;
4907}
Jack Carterd0bd6422013-04-18 00:41:53 +00004908
Jack Carter0b744b32012-10-04 02:29:46 +00004909bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004910 // Line can be: ".set at", which sets $at to $1
4911 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004912 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004913 Parser.Lex(); // Eat "at".
4914
Jack Carter0b744b32012-10-04 02:29:46 +00004915 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004916 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004917 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004918
4919 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004920 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004921 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004922 }
4923
4924 if (getLexer().isNot(AsmToken::Equal)) {
4925 reportParseError("unexpected token, expected equals sign");
4926 return false;
4927 }
4928 Parser.Lex(); // Eat "=".
4929
4930 if (getLexer().isNot(AsmToken::Dollar)) {
4931 if (getLexer().is(AsmToken::EndOfStatement)) {
4932 reportParseError("no register specified");
4933 return false;
4934 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004935 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004936 return false;
4937 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004938 }
4939 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004940
Toma Tabacu16a74492015-02-13 10:30:57 +00004941 // Find out what "reg" is.
4942 unsigned AtRegNo;
4943 const AsmToken &Reg = Parser.getTok();
4944 if (Reg.is(AsmToken::Identifier)) {
4945 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4946 } else if (Reg.is(AsmToken::Integer)) {
4947 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004948 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004949 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004950 return false;
4951 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004952
4953 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004954 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004955 reportParseError("invalid register");
4956 return false;
4957 }
4958 Parser.Lex(); // Eat "reg".
4959
4960 // If this is not the end of the statement, report an error.
4961 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4962 reportParseError("unexpected token, expected end of statement");
4963 return false;
4964 }
4965
4966 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4967
4968 Parser.Lex(); // Consume the EndOfStatement.
4969 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004970}
4971
4972bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004973 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004974 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004975 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004976 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004977 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004978 return false;
4979 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004980 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004981 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004982 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004983 return false;
4984}
4985
4986bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004987 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004988 Parser.Lex();
4989 // If this is not the end of the statement, report an error.
4990 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004991 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004992 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004993 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004994 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004995 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004996 Parser.Lex(); // Consume the EndOfStatement.
4997 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004998}
4999
5000bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005001 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005002 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005003 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005004 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005005 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005006 return false;
5007 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005008 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005009 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005010 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005011 return false;
5012}
5013
5014bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005015 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005016 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005017 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005018 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005019 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005020 return false;
5021 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005022 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005023 reportParseError("`noreorder' must be set before `nomacro'");
5024 return false;
5025 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005026 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005027 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005028 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005029 return false;
5030}
Jack Carterd76b2372013-03-21 21:44:16 +00005031
Daniel Sanders44934432014-08-07 12:03:36 +00005032bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005033 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005034 Parser.Lex();
5035
5036 // If this is not the end of the statement, report an error.
5037 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005038 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005039
5040 setFeatureBits(Mips::FeatureMSA, "msa");
5041 getTargetStreamer().emitDirectiveSetMsa();
5042 return false;
5043}
5044
5045bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005046 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005047 Parser.Lex();
5048
5049 // If this is not the end of the statement, report an error.
5050 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005051 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005052
5053 clearFeatureBits(Mips::FeatureMSA, "msa");
5054 getTargetStreamer().emitDirectiveSetNoMsa();
5055 return false;
5056}
5057
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005058bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005059 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005060 Parser.Lex(); // Eat "nodsp".
5061
5062 // If this is not the end of the statement, report an error.
5063 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5064 reportParseError("unexpected token, expected end of statement");
5065 return false;
5066 }
5067
5068 clearFeatureBits(Mips::FeatureDSP, "dsp");
5069 getTargetStreamer().emitDirectiveSetNoDsp();
5070 return false;
5071}
5072
Toma Tabacucc2502d2014-11-04 17:18:07 +00005073bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005074 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005075 Parser.Lex(); // Eat "mips16".
5076
Jack Carter39536722014-01-22 23:08:42 +00005077 // If this is not the end of the statement, report an error.
5078 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005079 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005080 return false;
5081 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005082
5083 setFeatureBits(Mips::FeatureMips16, "mips16");
5084 getTargetStreamer().emitDirectiveSetMips16();
5085 Parser.Lex(); // Consume the EndOfStatement.
5086 return false;
5087}
5088
5089bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005090 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005091 Parser.Lex(); // Eat "nomips16".
5092
5093 // If this is not the end of the statement, report an error.
5094 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5095 reportParseError("unexpected token, expected end of statement");
5096 return false;
5097 }
5098
5099 clearFeatureBits(Mips::FeatureMips16, "mips16");
5100 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005101 Parser.Lex(); // Consume the EndOfStatement.
5102 return false;
5103}
5104
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005105bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005106 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005107 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005108 // Line can be: .set fp=32
5109 // .set fp=xx
5110 // .set fp=64
5111 Parser.Lex(); // Eat fp token
5112 AsmToken Tok = Parser.getTok();
5113 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005114 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005115 return false;
5116 }
5117 Parser.Lex(); // Eat '=' token.
5118 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005119
5120 if (!parseFpABIValue(FpAbiVal, ".set"))
5121 return false;
5122
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005123 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005124 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005125 return false;
5126 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005127 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005128 Parser.Lex(); // Consume the EndOfStatement.
5129 return false;
5130}
5131
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005132bool MipsAsmParser::parseSetOddSPRegDirective() {
5133 MCAsmParser &Parser = getParser();
5134
5135 Parser.Lex(); // Eat "oddspreg".
5136 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5137 reportParseError("unexpected token, expected end of statement");
5138 return false;
5139 }
5140
5141 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5142 getTargetStreamer().emitDirectiveSetOddSPReg();
5143 return false;
5144}
5145
5146bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5147 MCAsmParser &Parser = getParser();
5148
5149 Parser.Lex(); // Eat "nooddspreg".
5150 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5151 reportParseError("unexpected token, expected end of statement");
5152 return false;
5153 }
5154
5155 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5156 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5157 return false;
5158}
5159
Toma Tabacu9db22db2014-09-09 10:15:38 +00005160bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005161 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005162 SMLoc Loc = getLexer().getLoc();
5163
5164 Parser.Lex();
5165 if (getLexer().isNot(AsmToken::EndOfStatement))
5166 return reportParseError("unexpected token, expected end of statement");
5167
5168 // Always keep an element on the options "stack" to prevent the user
5169 // from changing the initial options. This is how we remember them.
5170 if (AssemblerOptions.size() == 2)
5171 return reportParseError(Loc, ".set pop with no .set push");
5172
Akira Hatanakab11ef082015-11-14 06:35:56 +00005173 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005174 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005175 setAvailableFeatures(
5176 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5177 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005178
5179 getTargetStreamer().emitDirectiveSetPop();
5180 return false;
5181}
5182
5183bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005184 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005185 Parser.Lex();
5186 if (getLexer().isNot(AsmToken::EndOfStatement))
5187 return reportParseError("unexpected token, expected end of statement");
5188
5189 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005190 AssemblerOptions.push_back(
5191 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005192
5193 getTargetStreamer().emitDirectiveSetPush();
5194 return false;
5195}
5196
Toma Tabacu29696502015-06-02 09:48:04 +00005197bool MipsAsmParser::parseSetSoftFloatDirective() {
5198 MCAsmParser &Parser = getParser();
5199 Parser.Lex();
5200 if (getLexer().isNot(AsmToken::EndOfStatement))
5201 return reportParseError("unexpected token, expected end of statement");
5202
5203 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5204 getTargetStreamer().emitDirectiveSetSoftFloat();
5205 return false;
5206}
5207
5208bool MipsAsmParser::parseSetHardFloatDirective() {
5209 MCAsmParser &Parser = getParser();
5210 Parser.Lex();
5211 if (getLexer().isNot(AsmToken::EndOfStatement))
5212 return reportParseError("unexpected token, expected end of statement");
5213
5214 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5215 getTargetStreamer().emitDirectiveSetHardFloat();
5216 return false;
5217}
5218
Jack Carterd76b2372013-03-21 21:44:16 +00005219bool MipsAsmParser::parseSetAssignment() {
5220 StringRef Name;
5221 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005222 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005223
5224 if (Parser.parseIdentifier(Name))
5225 reportParseError("expected identifier after .set");
5226
5227 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005228 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005229 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005230
Jack Carter3b2c96e2014-01-22 23:31:38 +00005231 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005232 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005233
Jim Grosbach6f482002015-05-18 18:43:14 +00005234 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005235 Sym->setVariableValue(Value);
5236
5237 return false;
5238}
Jack Carterd0bd6422013-04-18 00:41:53 +00005239
Toma Tabacu26647792014-09-09 12:52:14 +00005240bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005241 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005242 Parser.Lex();
5243 if (getLexer().isNot(AsmToken::EndOfStatement))
5244 return reportParseError("unexpected token, expected end of statement");
5245
5246 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005247 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005248 setAvailableFeatures(
5249 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5250 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005251 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5252
5253 getTargetStreamer().emitDirectiveSetMips0();
5254 return false;
5255}
5256
Toma Tabacu85618b32014-08-19 14:22:52 +00005257bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005258 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005259 Parser.Lex();
5260 if (getLexer().isNot(AsmToken::Equal))
5261 return reportParseError("unexpected token, expected equals sign");
5262
5263 Parser.Lex();
5264 StringRef Arch;
5265 if (Parser.parseIdentifier(Arch))
5266 return reportParseError("expected arch identifier");
5267
5268 StringRef ArchFeatureName =
5269 StringSwitch<StringRef>(Arch)
5270 .Case("mips1", "mips1")
5271 .Case("mips2", "mips2")
5272 .Case("mips3", "mips3")
5273 .Case("mips4", "mips4")
5274 .Case("mips5", "mips5")
5275 .Case("mips32", "mips32")
5276 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005277 .Case("mips32r3", "mips32r3")
5278 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005279 .Case("mips32r6", "mips32r6")
5280 .Case("mips64", "mips64")
5281 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005282 .Case("mips64r3", "mips64r3")
5283 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005284 .Case("mips64r6", "mips64r6")
5285 .Case("cnmips", "cnmips")
5286 .Case("r4000", "mips3") // This is an implementation of Mips3.
5287 .Default("");
5288
5289 if (ArchFeatureName.empty())
5290 return reportParseError("unsupported architecture");
5291
5292 selectArch(ArchFeatureName);
5293 getTargetStreamer().emitDirectiveSetArch(Arch);
5294 return false;
5295}
5296
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005297bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005298 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005299 Parser.Lex();
5300 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005301 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005302
Matheus Almeida2852af82014-04-22 10:15:54 +00005303 switch (Feature) {
5304 default:
5305 llvm_unreachable("Unimplemented feature");
5306 case Mips::FeatureDSP:
5307 setFeatureBits(Mips::FeatureDSP, "dsp");
5308 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005309 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005310 case Mips::FeatureMicroMips:
5311 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005312 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005313 case Mips::FeatureMips1:
5314 selectArch("mips1");
5315 getTargetStreamer().emitDirectiveSetMips1();
5316 break;
5317 case Mips::FeatureMips2:
5318 selectArch("mips2");
5319 getTargetStreamer().emitDirectiveSetMips2();
5320 break;
5321 case Mips::FeatureMips3:
5322 selectArch("mips3");
5323 getTargetStreamer().emitDirectiveSetMips3();
5324 break;
5325 case Mips::FeatureMips4:
5326 selectArch("mips4");
5327 getTargetStreamer().emitDirectiveSetMips4();
5328 break;
5329 case Mips::FeatureMips5:
5330 selectArch("mips5");
5331 getTargetStreamer().emitDirectiveSetMips5();
5332 break;
5333 case Mips::FeatureMips32:
5334 selectArch("mips32");
5335 getTargetStreamer().emitDirectiveSetMips32();
5336 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005337 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005338 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005339 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005340 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005341 case Mips::FeatureMips32r3:
5342 selectArch("mips32r3");
5343 getTargetStreamer().emitDirectiveSetMips32R3();
5344 break;
5345 case Mips::FeatureMips32r5:
5346 selectArch("mips32r5");
5347 getTargetStreamer().emitDirectiveSetMips32R5();
5348 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005349 case Mips::FeatureMips32r6:
5350 selectArch("mips32r6");
5351 getTargetStreamer().emitDirectiveSetMips32R6();
5352 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005353 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005354 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005355 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005356 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005357 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005358 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005359 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005360 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005361 case Mips::FeatureMips64r3:
5362 selectArch("mips64r3");
5363 getTargetStreamer().emitDirectiveSetMips64R3();
5364 break;
5365 case Mips::FeatureMips64r5:
5366 selectArch("mips64r5");
5367 getTargetStreamer().emitDirectiveSetMips64R5();
5368 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005369 case Mips::FeatureMips64r6:
5370 selectArch("mips64r6");
5371 getTargetStreamer().emitDirectiveSetMips64R6();
5372 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005373 }
5374 return false;
5375}
5376
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005377bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005378 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005379 if (getLexer().isNot(AsmToken::Comma)) {
5380 SMLoc Loc = getLexer().getLoc();
5381 Parser.eatToEndOfStatement();
5382 return Error(Loc, ErrorStr);
5383 }
5384
Matheus Almeida2852af82014-04-22 10:15:54 +00005385 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005386 return true;
5387}
5388
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005389// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5390// In this class, it is only used for .cprestore.
5391// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5392// MipsTargetELFStreamer and MipsAsmParser.
5393bool MipsAsmParser::isPicAndNotNxxAbi() {
5394 return inPicMode() && !(isABI_N32() || isABI_N64());
5395}
5396
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005397bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005398 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005399 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005400
Toma Tabacudde4c462014-11-06 10:02:45 +00005401 if (inMips16Mode()) {
5402 reportParseError(".cpload is not supported in Mips16 mode");
5403 return false;
5404 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005405
David Blaikie960ea3f2014-06-08 16:18:35 +00005406 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005407 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005408 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5409 reportParseError("expected register containing function address");
5410 return false;
5411 }
5412
David Blaikie960ea3f2014-06-08 16:18:35 +00005413 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5414 if (!RegOpnd.isGPRAsmReg()) {
5415 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005416 return false;
5417 }
5418
Toma Tabacudde4c462014-11-06 10:02:45 +00005419 // If this is not the end of the statement, report an error.
5420 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5421 reportParseError("unexpected token, expected end of statement");
5422 return false;
5423 }
5424
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005425 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005426 return false;
5427}
5428
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005429bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5430 MCAsmParser &Parser = getParser();
5431
5432 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5433 // is used in non-PIC mode.
5434
5435 if (inMips16Mode()) {
5436 reportParseError(".cprestore is not supported in Mips16 mode");
5437 return false;
5438 }
5439
5440 // Get the stack offset value.
5441 const MCExpr *StackOffset;
5442 int64_t StackOffsetVal;
5443 if (Parser.parseExpression(StackOffset)) {
5444 reportParseError("expected stack offset value");
5445 return false;
5446 }
5447
5448 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5449 reportParseError("stack offset is not an absolute expression");
5450 return false;
5451 }
5452
5453 if (StackOffsetVal < 0) {
5454 Warning(Loc, ".cprestore with negative stack offset has no effect");
5455 IsCpRestoreSet = false;
5456 } else {
5457 IsCpRestoreSet = true;
5458 CpRestoreOffset = StackOffsetVal;
5459 }
5460
5461 // If this is not the end of the statement, report an error.
5462 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5463 reportParseError("unexpected token, expected end of statement");
5464 return false;
5465 }
5466
5467 // Store the $gp on the stack.
5468 SmallVector<MCInst, 3> StoreInsts;
5469 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5470 StoreInsts);
5471
5472 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5473 Parser.Lex(); // Consume the EndOfStatement.
5474 return false;
5475}
5476
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005477bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005478 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005479 unsigned FuncReg;
5480 unsigned Save;
5481 bool SaveIsReg = true;
5482
Matheus Almeida7e815762014-06-18 13:08:59 +00005483 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005484 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005485 if (ResTy == MatchOperand_NoMatch) {
5486 reportParseError("expected register containing function address");
5487 Parser.eatToEndOfStatement();
5488 return false;
5489 }
5490
5491 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5492 if (!FuncRegOpnd.isGPRAsmReg()) {
5493 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5494 Parser.eatToEndOfStatement();
5495 return false;
5496 }
5497
5498 FuncReg = FuncRegOpnd.getGPR32Reg();
5499 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005500
Toma Tabacu65f10572014-09-16 15:00:52 +00005501 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005502 return true;
5503
Toma Tabacu13964452014-09-04 13:23:44 +00005504 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005505 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005506 const MCExpr *OffsetExpr;
5507 int64_t OffsetVal;
5508 SMLoc ExprLoc = getLexer().getLoc();
5509
5510 if (Parser.parseExpression(OffsetExpr) ||
5511 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5512 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005513 Parser.eatToEndOfStatement();
5514 return false;
5515 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005516
5517 Save = OffsetVal;
5518 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005519 } else {
5520 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5521 if (!SaveOpnd.isGPRAsmReg()) {
5522 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5523 Parser.eatToEndOfStatement();
5524 return false;
5525 }
5526 Save = SaveOpnd.getGPR32Reg();
5527 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005528
Toma Tabacu65f10572014-09-16 15:00:52 +00005529 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005530 return true;
5531
Toma Tabacu8874eac2015-02-18 13:46:53 +00005532 const MCExpr *Expr;
5533 if (Parser.parseExpression(Expr)) {
5534 reportParseError("expected expression");
5535 return false;
5536 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005537
Toma Tabacu8874eac2015-02-18 13:46:53 +00005538 if (Expr->getKind() != MCExpr::SymbolRef) {
5539 reportParseError("expected symbol");
5540 return false;
5541 }
5542 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5543
Daniel Sandersf173dda2015-09-22 10:50:09 +00005544 CpSaveLocation = Save;
5545 CpSaveLocationIsRegister = SaveIsReg;
5546
Toma Tabacu8874eac2015-02-18 13:46:53 +00005547 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5548 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005549 return false;
5550}
5551
Daniel Sandersf173dda2015-09-22 10:50:09 +00005552bool MipsAsmParser::parseDirectiveCPReturn() {
5553 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5554 CpSaveLocationIsRegister);
5555 return false;
5556}
5557
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005558bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005559 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005560 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5561 const AsmToken &Tok = Parser.getTok();
5562
5563 if (Tok.getString() == "2008") {
5564 Parser.Lex();
5565 getTargetStreamer().emitDirectiveNaN2008();
5566 return false;
5567 } else if (Tok.getString() == "legacy") {
5568 Parser.Lex();
5569 getTargetStreamer().emitDirectiveNaNLegacy();
5570 return false;
5571 }
5572 }
5573 // If we don't recognize the option passed to the .nan
5574 // directive (e.g. no option or unknown option), emit an error.
5575 reportParseError("invalid option in .nan directive");
5576 return false;
5577}
5578
Jack Carter0b744b32012-10-04 02:29:46 +00005579bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005580 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005581 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005582 const AsmToken &Tok = Parser.getTok();
5583
5584 if (Tok.getString() == "noat") {
5585 return parseSetNoAtDirective();
5586 } else if (Tok.getString() == "at") {
5587 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005588 } else if (Tok.getString() == "arch") {
5589 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005590 } else if (Tok.getString() == "fp") {
5591 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005592 } else if (Tok.getString() == "oddspreg") {
5593 return parseSetOddSPRegDirective();
5594 } else if (Tok.getString() == "nooddspreg") {
5595 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005596 } else if (Tok.getString() == "pop") {
5597 return parseSetPopDirective();
5598 } else if (Tok.getString() == "push") {
5599 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005600 } else if (Tok.getString() == "reorder") {
5601 return parseSetReorderDirective();
5602 } else if (Tok.getString() == "noreorder") {
5603 return parseSetNoReorderDirective();
5604 } else if (Tok.getString() == "macro") {
5605 return parseSetMacroDirective();
5606 } else if (Tok.getString() == "nomacro") {
5607 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005608 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005609 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005610 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005611 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005612 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005613 getTargetStreamer().emitDirectiveSetNoMicroMips();
5614 Parser.eatToEndOfStatement();
5615 return false;
5616 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005617 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005618 } else if (Tok.getString() == "mips0") {
5619 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005620 } else if (Tok.getString() == "mips1") {
5621 return parseSetFeature(Mips::FeatureMips1);
5622 } else if (Tok.getString() == "mips2") {
5623 return parseSetFeature(Mips::FeatureMips2);
5624 } else if (Tok.getString() == "mips3") {
5625 return parseSetFeature(Mips::FeatureMips3);
5626 } else if (Tok.getString() == "mips4") {
5627 return parseSetFeature(Mips::FeatureMips4);
5628 } else if (Tok.getString() == "mips5") {
5629 return parseSetFeature(Mips::FeatureMips5);
5630 } else if (Tok.getString() == "mips32") {
5631 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005632 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005633 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005634 } else if (Tok.getString() == "mips32r3") {
5635 return parseSetFeature(Mips::FeatureMips32r3);
5636 } else if (Tok.getString() == "mips32r5") {
5637 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005638 } else if (Tok.getString() == "mips32r6") {
5639 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005640 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005641 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005642 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005643 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005644 } else if (Tok.getString() == "mips64r3") {
5645 return parseSetFeature(Mips::FeatureMips64r3);
5646 } else if (Tok.getString() == "mips64r5") {
5647 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005648 } else if (Tok.getString() == "mips64r6") {
5649 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005650 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005651 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005652 } else if (Tok.getString() == "nodsp") {
5653 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005654 } else if (Tok.getString() == "msa") {
5655 return parseSetMsaDirective();
5656 } else if (Tok.getString() == "nomsa") {
5657 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005658 } else if (Tok.getString() == "softfloat") {
5659 return parseSetSoftFloatDirective();
5660 } else if (Tok.getString() == "hardfloat") {
5661 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005662 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005663 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005664 parseSetAssignment();
5665 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005666 }
Jack Carter07c818d2013-01-25 01:31:34 +00005667
Jack Carter0b744b32012-10-04 02:29:46 +00005668 return true;
5669}
5670
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005671/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005672/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005673bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005674 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005675 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5676 for (;;) {
5677 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005678 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005679 return true;
5680
5681 getParser().getStreamer().EmitValue(Value, Size);
5682
5683 if (getLexer().is(AsmToken::EndOfStatement))
5684 break;
5685
Jack Carter07c818d2013-01-25 01:31:34 +00005686 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005687 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005688 Parser.Lex();
5689 }
5690 }
5691
5692 Parser.Lex();
5693 return false;
5694}
5695
Vladimir Medic4c299852013-11-06 11:27:05 +00005696/// parseDirectiveGpWord
5697/// ::= .gpword local_sym
5698bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005699 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005700 const MCExpr *Value;
5701 // EmitGPRel32Value requires an expression, so we are using base class
5702 // method to evaluate the expression.
5703 if (getParser().parseExpression(Value))
5704 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005705 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005706
Vladimir Medice10c1122013-11-13 13:18:04 +00005707 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005708 return Error(getLexer().getLoc(),
5709 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005710 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005711 return false;
5712}
5713
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005714/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005715/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005716bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005717 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005718 const MCExpr *Value;
5719 // EmitGPRel64Value requires an expression, so we are using base class
5720 // method to evaluate the expression.
5721 if (getParser().parseExpression(Value))
5722 return true;
5723 getParser().getStreamer().EmitGPRel64Value(Value);
5724
5725 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005726 return Error(getLexer().getLoc(),
5727 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005728 Parser.Lex(); // Eat EndOfStatement token.
5729 return false;
5730}
5731
Jack Carter0cd3c192014-01-06 23:27:31 +00005732bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005733 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005734 // Get the option token.
5735 AsmToken Tok = Parser.getTok();
5736 // At the moment only identifiers are supported.
5737 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005738 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005739 Parser.eatToEndOfStatement();
5740 return false;
5741 }
5742
5743 StringRef Option = Tok.getIdentifier();
5744
5745 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005746 // MipsAsmParser needs to know if the current PIC mode changes.
5747 IsPicEnabled = false;
5748
Jack Carter0cd3c192014-01-06 23:27:31 +00005749 getTargetStreamer().emitDirectiveOptionPic0();
5750 Parser.Lex();
5751 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5752 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005753 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005754 Parser.eatToEndOfStatement();
5755 }
5756 return false;
5757 }
5758
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005759 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005760 // MipsAsmParser needs to know if the current PIC mode changes.
5761 IsPicEnabled = true;
5762
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005763 getTargetStreamer().emitDirectiveOptionPic2();
5764 Parser.Lex();
5765 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5766 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005767 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005768 Parser.eatToEndOfStatement();
5769 }
5770 return false;
5771 }
5772
Jack Carter0cd3c192014-01-06 23:27:31 +00005773 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005774 Warning(Parser.getTok().getLoc(),
5775 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005776 Parser.eatToEndOfStatement();
5777 return false;
5778}
5779
Toma Tabacu9ca50962015-04-16 09:53:47 +00005780/// parseInsnDirective
5781/// ::= .insn
5782bool MipsAsmParser::parseInsnDirective() {
5783 // If this is not the end of the statement, report an error.
5784 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5785 reportParseError("unexpected token, expected end of statement");
5786 return false;
5787 }
5788
5789 // The actual label marking happens in
5790 // MipsELFStreamer::createPendingLabelRelocs().
5791 getTargetStreamer().emitDirectiveInsn();
5792
5793 getParser().Lex(); // Eat EndOfStatement token.
5794 return false;
5795}
5796
Simon Atanasyanbe186202016-02-11 06:45:54 +00005797/// parseSSectionDirective
5798/// ::= .sbss
5799/// ::= .sdata
5800bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5801 // If this is not the end of the statement, report an error.
5802 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5803 reportParseError("unexpected token, expected end of statement");
5804 return false;
5805 }
5806
5807 MCSection *ELFSection = getContext().getELFSection(
5808 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5809 getParser().getStreamer().SwitchSection(ELFSection);
5810
5811 getParser().Lex(); // Eat EndOfStatement token.
5812 return false;
5813}
5814
Daniel Sanders7e527422014-07-10 13:38:23 +00005815/// parseDirectiveModule
5816/// ::= .module oddspreg
5817/// ::= .module nooddspreg
5818/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005819/// ::= .module softfloat
5820/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005821bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005822 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005823 MCAsmLexer &Lexer = getLexer();
5824 SMLoc L = Lexer.getLoc();
5825
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005826 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005827 // TODO : get a better message.
5828 reportParseError(".module directive must appear before any code");
5829 return false;
5830 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005831
Toma Tabacuc405c822015-01-23 10:40:19 +00005832 StringRef Option;
5833 if (Parser.parseIdentifier(Option)) {
5834 reportParseError("expected .module option identifier");
5835 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005836 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005837
Toma Tabacuc405c822015-01-23 10:40:19 +00005838 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005839 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005840
Toma Tabacu3c499582015-06-25 10:56:57 +00005841 // Synchronize the abiflags information with the FeatureBits information we
5842 // changed above.
5843 getTargetStreamer().updateABIInfo(*this);
5844
5845 // If printing assembly, use the recently updated abiflags information.
5846 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5847 // emitted at the end).
5848 getTargetStreamer().emitDirectiveModuleOddSPReg();
5849
Toma Tabacuc405c822015-01-23 10:40:19 +00005850 // If this is not the end of the statement, report an error.
5851 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5852 reportParseError("unexpected token, expected end of statement");
5853 return false;
5854 }
5855
5856 return false; // parseDirectiveModule has finished successfully.
5857 } else if (Option == "nooddspreg") {
5858 if (!isABI_O32()) {
5859 Error(L, "'.module nooddspreg' requires the O32 ABI");
5860 return false;
5861 }
5862
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005863 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005864
Toma Tabacu3c499582015-06-25 10:56:57 +00005865 // Synchronize the abiflags information with the FeatureBits information we
5866 // changed above.
5867 getTargetStreamer().updateABIInfo(*this);
5868
5869 // If printing assembly, use the recently updated abiflags information.
5870 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5871 // emitted at the end).
5872 getTargetStreamer().emitDirectiveModuleOddSPReg();
5873
Toma Tabacuc405c822015-01-23 10:40:19 +00005874 // If this is not the end of the statement, report an error.
5875 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5876 reportParseError("unexpected token, expected end of statement");
5877 return false;
5878 }
5879
5880 return false; // parseDirectiveModule has finished successfully.
5881 } else if (Option == "fp") {
5882 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005883 } else if (Option == "softfloat") {
5884 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5885
5886 // Synchronize the ABI Flags information with the FeatureBits information we
5887 // updated above.
5888 getTargetStreamer().updateABIInfo(*this);
5889
5890 // If printing assembly, use the recently updated ABI Flags information.
5891 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5892 // emitted later).
5893 getTargetStreamer().emitDirectiveModuleSoftFloat();
5894
5895 // If this is not the end of the statement, report an error.
5896 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5897 reportParseError("unexpected token, expected end of statement");
5898 return false;
5899 }
5900
5901 return false; // parseDirectiveModule has finished successfully.
5902 } else if (Option == "hardfloat") {
5903 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5904
5905 // Synchronize the ABI Flags information with the FeatureBits information we
5906 // updated above.
5907 getTargetStreamer().updateABIInfo(*this);
5908
5909 // If printing assembly, use the recently updated ABI Flags information.
5910 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5911 // emitted later).
5912 getTargetStreamer().emitDirectiveModuleHardFloat();
5913
5914 // If this is not the end of the statement, report an error.
5915 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5916 reportParseError("unexpected token, expected end of statement");
5917 return false;
5918 }
5919
5920 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005921 } else {
5922 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5923 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005924}
5925
5926/// parseDirectiveModuleFP
5927/// ::= =32
5928/// ::= =xx
5929/// ::= =64
5930bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005931 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005932 MCAsmLexer &Lexer = getLexer();
5933
5934 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005935 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005936 return false;
5937 }
5938 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005939
Daniel Sanders7e527422014-07-10 13:38:23 +00005940 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005941 if (!parseFpABIValue(FpABI, ".module"))
5942 return false;
5943
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005944 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005945 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005946 return false;
5947 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005948
Toma Tabacua64e5402015-06-25 12:44:38 +00005949 // Synchronize the abiflags information with the FeatureBits information we
5950 // changed above.
5951 getTargetStreamer().updateABIInfo(*this);
5952
5953 // If printing assembly, use the recently updated abiflags information.
5954 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5955 // emitted at the end).
5956 getTargetStreamer().emitDirectiveModuleFP();
5957
Daniel Sanders7e527422014-07-10 13:38:23 +00005958 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005959 return false;
5960}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005961
Daniel Sanders7e527422014-07-10 13:38:23 +00005962bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005963 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005964 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005965 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005966 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005967
5968 if (Lexer.is(AsmToken::Identifier)) {
5969 StringRef Value = Parser.getTok().getString();
5970 Parser.Lex();
5971
5972 if (Value != "xx") {
5973 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5974 return false;
5975 }
5976
5977 if (!isABI_O32()) {
5978 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5979 return false;
5980 }
5981
Daniel Sanders7e527422014-07-10 13:38:23 +00005982 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005983 if (ModuleLevelOptions) {
5984 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5985 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5986 } else {
5987 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5988 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5989 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005990 return true;
5991 }
5992
5993 if (Lexer.is(AsmToken::Integer)) {
5994 unsigned Value = Parser.getTok().getIntVal();
5995 Parser.Lex();
5996
5997 if (Value != 32 && Value != 64) {
5998 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5999 return false;
6000 }
6001
6002 if (Value == 32) {
6003 if (!isABI_O32()) {
6004 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6005 return false;
6006 }
6007
Daniel Sanders7e527422014-07-10 13:38:23 +00006008 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006009 if (ModuleLevelOptions) {
6010 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6011 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6012 } else {
6013 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6014 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6015 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006016 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006017 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006018 if (ModuleLevelOptions) {
6019 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6020 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6021 } else {
6022 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6023 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6024 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006025 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006026
Daniel Sanders7e527422014-07-10 13:38:23 +00006027 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006028 }
6029
6030 return false;
6031}
6032
Jack Carter0b744b32012-10-04 02:29:46 +00006033bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006034 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006035 StringRef IDVal = DirectiveID.getString();
6036
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006037 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006038 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006039 if (IDVal == ".cprestore")
6040 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006041 if (IDVal == ".dword") {
6042 parseDataDirective(8, DirectiveID.getLoc());
6043 return false;
6044 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006045 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006046 StringRef SymbolName;
6047
6048 if (Parser.parseIdentifier(SymbolName)) {
6049 reportParseError("expected identifier after .ent");
6050 return false;
6051 }
6052
6053 // There's an undocumented extension that allows an integer to
6054 // follow the name of the procedure which AFAICS is ignored by GAS.
6055 // Example: .ent foo,2
6056 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6057 if (getLexer().isNot(AsmToken::Comma)) {
6058 // Even though we accept this undocumented extension for compatibility
6059 // reasons, the additional integer argument does not actually change
6060 // the behaviour of the '.ent' directive, so we would like to discourage
6061 // its use. We do this by not referring to the extended version in
6062 // error messages which are not directly related to its use.
6063 reportParseError("unexpected token, expected end of statement");
6064 return false;
6065 }
6066 Parser.Lex(); // Eat the comma.
6067 const MCExpr *DummyNumber;
6068 int64_t DummyNumberVal;
6069 // If the user was explicitly trying to use the extended version,
6070 // we still give helpful extension-related error messages.
6071 if (Parser.parseExpression(DummyNumber)) {
6072 reportParseError("expected number after comma");
6073 return false;
6074 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006075 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006076 reportParseError("expected an absolute expression after comma");
6077 return false;
6078 }
6079 }
6080
6081 // If this is not the end of the statement, report an error.
6082 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6083 reportParseError("unexpected token, expected end of statement");
6084 return false;
6085 }
6086
Jim Grosbach6f482002015-05-18 18:43:14 +00006087 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006088
6089 getTargetStreamer().emitDirectiveEnt(*Sym);
6090 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006091 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006092 return false;
6093 }
6094
Jack Carter07c818d2013-01-25 01:31:34 +00006095 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006096 StringRef SymbolName;
6097
6098 if (Parser.parseIdentifier(SymbolName)) {
6099 reportParseError("expected identifier after .end");
6100 return false;
6101 }
6102
6103 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6104 reportParseError("unexpected token, expected end of statement");
6105 return false;
6106 }
6107
6108 if (CurrentFn == nullptr) {
6109 reportParseError(".end used without .ent");
6110 return false;
6111 }
6112
6113 if ((SymbolName != CurrentFn->getName())) {
6114 reportParseError(".end symbol does not match .ent symbol");
6115 return false;
6116 }
6117
6118 getTargetStreamer().emitDirectiveEnd(SymbolName);
6119 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006120 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006121 return false;
6122 }
6123
Jack Carter07c818d2013-01-25 01:31:34 +00006124 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006125 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6126 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006127 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006128 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6129 reportParseError("expected stack register");
6130 return false;
6131 }
6132
6133 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6134 if (!StackRegOpnd.isGPRAsmReg()) {
6135 reportParseError(StackRegOpnd.getStartLoc(),
6136 "expected general purpose register");
6137 return false;
6138 }
6139 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6140
6141 if (Parser.getTok().is(AsmToken::Comma))
6142 Parser.Lex();
6143 else {
6144 reportParseError("unexpected token, expected comma");
6145 return false;
6146 }
6147
6148 // Parse the frame size.
6149 const MCExpr *FrameSize;
6150 int64_t FrameSizeVal;
6151
6152 if (Parser.parseExpression(FrameSize)) {
6153 reportParseError("expected frame size value");
6154 return false;
6155 }
6156
Jim Grosbach13760bd2015-05-30 01:25:56 +00006157 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006158 reportParseError("frame size not an absolute expression");
6159 return false;
6160 }
6161
6162 if (Parser.getTok().is(AsmToken::Comma))
6163 Parser.Lex();
6164 else {
6165 reportParseError("unexpected token, expected comma");
6166 return false;
6167 }
6168
6169 // Parse the return register.
6170 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006171 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006172 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6173 reportParseError("expected return register");
6174 return false;
6175 }
6176
6177 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6178 if (!ReturnRegOpnd.isGPRAsmReg()) {
6179 reportParseError(ReturnRegOpnd.getStartLoc(),
6180 "expected general purpose register");
6181 return false;
6182 }
6183
6184 // If this is not the end of the statement, report an error.
6185 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6186 reportParseError("unexpected token, expected end of statement");
6187 return false;
6188 }
6189
6190 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6191 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006192 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006193 return false;
6194 }
6195
Jack Carter07c818d2013-01-25 01:31:34 +00006196 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00006197 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00006198 }
6199
Daniel Sandersd97a6342014-08-13 10:07:34 +00006200 if (IDVal == ".mask" || IDVal == ".fmask") {
6201 // .mask bitmask, frame_offset
6202 // bitmask: One bit for each register used.
6203 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6204 // first register is expected to be saved.
6205 // Examples:
6206 // .mask 0x80000000, -4
6207 // .fmask 0x80000000, -4
6208 //
Jack Carterbe332172012-09-07 00:48:02 +00006209
Daniel Sandersd97a6342014-08-13 10:07:34 +00006210 // Parse the bitmask
6211 const MCExpr *BitMask;
6212 int64_t BitMaskVal;
6213
6214 if (Parser.parseExpression(BitMask)) {
6215 reportParseError("expected bitmask value");
6216 return false;
6217 }
6218
Jim Grosbach13760bd2015-05-30 01:25:56 +00006219 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006220 reportParseError("bitmask not an absolute expression");
6221 return false;
6222 }
6223
6224 if (Parser.getTok().is(AsmToken::Comma))
6225 Parser.Lex();
6226 else {
6227 reportParseError("unexpected token, expected comma");
6228 return false;
6229 }
6230
6231 // Parse the frame_offset
6232 const MCExpr *FrameOffset;
6233 int64_t FrameOffsetVal;
6234
6235 if (Parser.parseExpression(FrameOffset)) {
6236 reportParseError("expected frame offset value");
6237 return false;
6238 }
6239
Jim Grosbach13760bd2015-05-30 01:25:56 +00006240 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006241 reportParseError("frame offset not an absolute expression");
6242 return false;
6243 }
6244
6245 // If this is not the end of the statement, report an error.
6246 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6247 reportParseError("unexpected token, expected end of statement");
6248 return false;
6249 }
6250
6251 if (IDVal == ".mask")
6252 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6253 else
6254 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006255 return false;
6256 }
6257
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006258 if (IDVal == ".nan")
6259 return parseDirectiveNaN();
6260
Jack Carter07c818d2013-01-25 01:31:34 +00006261 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006262 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006263 return false;
6264 }
6265
Rafael Espindolab59fb732014-03-28 18:50:26 +00006266 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006267 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006268 return false;
6269 }
6270
Jack Carter07c818d2013-01-25 01:31:34 +00006271 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006272 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006273 return false;
6274 }
6275
Scott Egertond1aeb052016-02-15 16:11:51 +00006276 if (IDVal == ".hword") {
6277 parseDataDirective(2, DirectiveID.getLoc());
6278 return false;
6279 }
6280
Jack Carter0cd3c192014-01-06 23:27:31 +00006281 if (IDVal == ".option")
6282 return parseDirectiveOption();
6283
6284 if (IDVal == ".abicalls") {
6285 getTargetStreamer().emitDirectiveAbiCalls();
6286 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006287 Error(Parser.getTok().getLoc(),
6288 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006289 // Clear line
6290 Parser.eatToEndOfStatement();
6291 }
6292 return false;
6293 }
6294
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006295 if (IDVal == ".cpsetup")
6296 return parseDirectiveCPSetup();
6297
Daniel Sandersf173dda2015-09-22 10:50:09 +00006298 if (IDVal == ".cpreturn")
6299 return parseDirectiveCPReturn();
6300
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006301 if (IDVal == ".module")
6302 return parseDirectiveModule();
6303
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006304 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
6305 return parseInternalDirectiveReallowModule();
6306
Toma Tabacu9ca50962015-04-16 09:53:47 +00006307 if (IDVal == ".insn")
6308 return parseInsnDirective();
6309
Simon Atanasyanbe186202016-02-11 06:45:54 +00006310 if (IDVal == ".sbss")
6311 return parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6312 if (IDVal == ".sdata")
6313 return parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6314
Rafael Espindola870c4e92012-01-11 03:56:41 +00006315 return true;
6316}
6317
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006318bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6319 // If this is not the end of the statement, report an error.
6320 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6321 reportParseError("unexpected token, expected end of statement");
6322 return false;
6323 }
6324
6325 getTargetStreamer().reallowModuleDirective();
6326
6327 getParser().Lex(); // Eat EndOfStatement token.
6328 return false;
6329}
6330
Rafael Espindola870c4e92012-01-11 03:56:41 +00006331extern "C" void LLVMInitializeMipsAsmParser() {
6332 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6333 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6334 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6335 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6336}
Jack Carterb4dbc172012-09-05 23:34:03 +00006337
6338#define GET_REGISTER_MATCHER
6339#define GET_MATCHER_IMPLEMENTATION
6340#include "MipsGenAsmMatcher.inc"