blob: b1f9d20ebffc9649516c674dbf9e425e5226667a [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 }
Craig Topper56c590a2014-04-29 07:58:02 +00001035 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001036 // Note: It's not possible to pretend that other operand kinds are tokens.
1037 // The matcher emitter checks tokens first.
1038 return Kind == k_Token;
1039 }
Craig Topper56c590a2014-04-29 07:58:02 +00001040 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001041 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001042 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001043 }
1044 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001045 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1046 && getMemBase()->isGPRAsmReg();
1047 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001048 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
1049 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
1050 getMemBase()->isGPRAsmReg();
1051 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001052 bool isMemWithGRPMM16Base() const {
1053 return isMem() && getMemBase()->isMM16AsmReg();
1054 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001055 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1056 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1057 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1058 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001059 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1060 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1061 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1062 && (getMemBase()->getGPR32Reg() == Mips::SP);
1063 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001064 template <unsigned Bits, unsigned ShiftLeftAmount>
1065 bool isScaledUImm() const {
1066 return isConstantImm() &&
1067 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001068 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001069 bool isRegList16() const {
1070 if (!isRegList())
1071 return false;
1072
1073 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001074 if (Size < 2 || Size > 5)
1075 return false;
1076
1077 unsigned R0 = RegList.List->front();
1078 unsigned R1 = RegList.List->back();
1079 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1080 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001081 return false;
1082
1083 int PrevReg = *RegList.List->begin();
1084 for (int i = 1; i < Size - 1; i++) {
1085 int Reg = (*(RegList.List))[i];
1086 if ( Reg != PrevReg + 1)
1087 return false;
1088 PrevReg = Reg;
1089 }
1090
1091 return true;
1092 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001093 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001094 bool isLSAImm() const {
1095 if (!isConstantImm())
1096 return false;
1097 int64_t Val = getConstantImm();
1098 return 1 <= Val && Val <= 4;
1099 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001100 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001101 bool isMovePRegPair() const {
1102 if (Kind != k_RegList || RegList.List->size() != 2)
1103 return false;
1104
1105 unsigned R0 = RegList.List->front();
1106 unsigned R1 = RegList.List->back();
1107
1108 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1109 (R0 == Mips::A1 && R1 == Mips::A3) ||
1110 (R0 == Mips::A2 && R1 == Mips::A3) ||
1111 (R0 == Mips::A0 && R1 == Mips::S5) ||
1112 (R0 == Mips::A0 && R1 == Mips::S6) ||
1113 (R0 == Mips::A0 && R1 == Mips::A1) ||
1114 (R0 == Mips::A0 && R1 == Mips::A2) ||
1115 (R0 == Mips::A0 && R1 == Mips::A3))
1116 return true;
1117
1118 return false;
1119 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001120
1121 StringRef getToken() const {
1122 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001123 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001124 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001125 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001126
Craig Topper56c590a2014-04-29 07:58:02 +00001127 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001128 // As a special case until we sort out the definition of div/divu, pretend
1129 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1130 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1131 RegIdx.Kind & RegKind_GPR)
1132 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001133
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001134 assert(Kind == k_PhysRegister && "Invalid access!");
1135 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001136 }
1137
Jack Carterb4dbc172012-09-05 23:34:03 +00001138 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001139 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001140 return Imm.Val;
1141 }
1142
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001143 int64_t getConstantImm() const {
1144 const MCExpr *Val = getImm();
1145 return static_cast<const MCConstantExpr *>(Val)->getValue();
1146 }
1147
1148 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001149 assert((Kind == k_Memory) && "Invalid access!");
1150 return Mem.Base;
1151 }
1152
1153 const MCExpr *getMemOff() const {
1154 assert((Kind == k_Memory) && "Invalid access!");
1155 return Mem.Off;
1156 }
1157
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001158 int64_t getConstantMemOff() const {
1159 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1160 }
1161
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001162 const SmallVectorImpl<unsigned> &getRegList() const {
1163 assert((Kind == k_RegList) && "Invalid access!");
1164 return *(RegList.List);
1165 }
1166
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001167 unsigned getRegPair() const {
1168 assert((Kind == k_RegPair) && "Invalid access!");
1169 return RegIdx.Index;
1170 }
1171
David Blaikie960ea3f2014-06-08 16:18:35 +00001172 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1173 MipsAsmParser &Parser) {
1174 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001175 Op->Tok.Data = Str.data();
1176 Op->Tok.Length = Str.size();
1177 Op->StartLoc = S;
1178 Op->EndLoc = S;
1179 return Op;
1180 }
1181
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001182 /// Create a numeric register (e.g. $1). The exact register remains
1183 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001184 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001185 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001186 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001187 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001188 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001189 }
1190
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001191 /// Create a register that is definitely a GPR.
1192 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001193 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001194 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001195 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001196 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001197 }
1198
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001199 /// Create a register that is definitely a FGR.
1200 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001201 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001202 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001203 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001204 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1205 }
1206
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001207 /// Create a register that is definitely a HWReg.
1208 /// This is typically only used for named registers such as $hwr_cpunum.
1209 static std::unique_ptr<MipsOperand>
1210 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1211 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1212 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1213 }
1214
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001215 /// Create a register that is definitely an FCC.
1216 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001217 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001218 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001219 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001220 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1221 }
1222
1223 /// Create a register that is definitely an ACC.
1224 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001225 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001226 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001227 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001228 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1229 }
1230
1231 /// Create a register that is definitely an MSA128.
1232 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001233 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001234 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001235 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001236 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1237 }
1238
1239 /// Create a register that is definitely an MSACtrl.
1240 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001241 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001242 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001243 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001244 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1245 }
1246
David Blaikie960ea3f2014-06-08 16:18:35 +00001247 static std::unique_ptr<MipsOperand>
1248 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1249 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001250 Op->Imm.Val = Val;
1251 Op->StartLoc = S;
1252 Op->EndLoc = E;
1253 return Op;
1254 }
1255
David Blaikie960ea3f2014-06-08 16:18:35 +00001256 static std::unique_ptr<MipsOperand>
1257 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1258 SMLoc E, MipsAsmParser &Parser) {
1259 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1260 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001261 Op->Mem.Off = Off;
1262 Op->StartLoc = S;
1263 Op->EndLoc = E;
1264 return Op;
1265 }
1266
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001267 static std::unique_ptr<MipsOperand>
1268 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1269 MipsAsmParser &Parser) {
1270 assert (Regs.size() > 0 && "Empty list not allowed");
1271
1272 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001273 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001274 Op->StartLoc = StartLoc;
1275 Op->EndLoc = EndLoc;
1276 return Op;
1277 }
1278
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001279 static std::unique_ptr<MipsOperand>
1280 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1281 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1282 Op->RegIdx.Index = RegNo;
1283 Op->StartLoc = S;
1284 Op->EndLoc = E;
1285 return Op;
1286 }
1287
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001288 bool isGPRAsmReg() const {
1289 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001290 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001291 bool isMM16AsmReg() const {
1292 if (!(isRegIdx() && RegIdx.Kind))
1293 return false;
1294 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1295 || RegIdx.Index == 16 || RegIdx.Index == 17);
1296 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001297 bool isMM16AsmRegZero() const {
1298 if (!(isRegIdx() && RegIdx.Kind))
1299 return false;
1300 return (RegIdx.Index == 0 ||
1301 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1302 RegIdx.Index == 17);
1303 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001304 bool isMM16AsmRegMoveP() const {
1305 if (!(isRegIdx() && RegIdx.Kind))
1306 return false;
1307 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1308 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1309 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001310 bool isFGRAsmReg() const {
1311 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1312 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001313 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001314 bool isHWRegsAsmReg() const {
1315 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001316 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001317 bool isCCRAsmReg() const {
1318 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001319 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001320 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001321 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1322 return false;
1323 if (!AsmParser.hasEightFccRegisters())
1324 return RegIdx.Index == 0;
1325 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001326 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001327 bool isACCAsmReg() const {
1328 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001329 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001330 bool isCOP0AsmReg() const {
1331 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1332 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001333 bool isCOP2AsmReg() const {
1334 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001335 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001336 bool isCOP3AsmReg() const {
1337 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1338 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001339 bool isMSA128AsmReg() const {
1340 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001341 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001342 bool isMSACtrlAsmReg() const {
1343 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001344 }
1345
Jack Carterb4dbc172012-09-05 23:34:03 +00001346 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001347 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001348 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001349 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001350
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001351 virtual ~MipsOperand() {
1352 switch (Kind) {
1353 case k_Immediate:
1354 break;
1355 case k_Memory:
1356 delete Mem.Base;
1357 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001358 case k_RegList:
1359 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001360 case k_PhysRegister:
1361 case k_RegisterIndex:
1362 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001363 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001364 break;
1365 }
1366 }
1367
Craig Topper56c590a2014-04-29 07:58:02 +00001368 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001369 switch (Kind) {
1370 case k_Immediate:
1371 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001372 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001373 OS << ">";
1374 break;
1375 case k_Memory:
1376 OS << "Mem<";
1377 Mem.Base->print(OS);
1378 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001379 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001380 OS << ">";
1381 break;
1382 case k_PhysRegister:
1383 OS << "PhysReg<" << PhysReg.Num << ">";
1384 break;
1385 case k_RegisterIndex:
1386 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1387 break;
1388 case k_Token:
1389 OS << Tok.Data;
1390 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001391 case k_RegList:
1392 OS << "RegList< ";
1393 for (auto Reg : (*RegList.List))
1394 OS << Reg << " ";
1395 OS << ">";
1396 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001397 case k_RegPair:
1398 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1399 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001400 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001401 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001402}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001403} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001404
Jack Carter9e65aa32013-03-22 00:05:30 +00001405namespace llvm {
1406extern const MCInstrDesc MipsInsts[];
1407}
1408static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1409 return MipsInsts[Opcode];
1410}
1411
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001412static bool hasShortDelaySlot(unsigned Opcode) {
1413 switch (Opcode) {
1414 case Mips::JALS_MM:
1415 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001416 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001417 case Mips::BGEZALS_MM:
1418 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001419 return true;
1420 default:
1421 return false;
1422 }
1423}
1424
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001425static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1426 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1427 return &SRExpr->getSymbol();
1428 }
1429
1430 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1431 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1432 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1433
1434 if (LHSSym)
1435 return LHSSym;
1436
1437 if (RHSSym)
1438 return RHSSym;
1439
1440 return nullptr;
1441 }
1442
1443 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1444 return getSingleMCSymbol(UExpr->getSubExpr());
1445
1446 return nullptr;
1447}
1448
1449static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1450 if (isa<MCSymbolRefExpr>(Expr))
1451 return 1;
1452
1453 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1454 return countMCSymbolRefExpr(BExpr->getLHS()) +
1455 countMCSymbolRefExpr(BExpr->getRHS());
1456
1457 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1458 return countMCSymbolRefExpr(UExpr->getSubExpr());
1459
1460 return 0;
1461}
1462
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001463namespace {
1464void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1465 SmallVectorImpl<MCInst> &Instructions) {
1466 MCInst tmpInst;
1467 tmpInst.setOpcode(Opcode);
1468 tmpInst.addOperand(MCOperand::createReg(Reg0));
1469 tmpInst.addOperand(Op1);
1470 tmpInst.setLoc(IDLoc);
1471 Instructions.push_back(tmpInst);
1472}
1473
1474void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1475 SmallVectorImpl<MCInst> &Instructions) {
1476 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1477}
1478
1479void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1480 SmallVectorImpl<MCInst> &Instructions) {
1481 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1482}
1483
1484void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1485 SmallVectorImpl<MCInst> &Instructions) {
1486 MCInst tmpInst;
1487 tmpInst.setOpcode(Opcode);
1488 tmpInst.addOperand(MCOperand::createImm(Imm1));
1489 tmpInst.addOperand(MCOperand::createImm(Imm2));
1490 tmpInst.setLoc(IDLoc);
1491 Instructions.push_back(tmpInst);
1492}
1493
1494void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1495 SmallVectorImpl<MCInst> &Instructions) {
1496 MCInst tmpInst;
1497 tmpInst.setOpcode(Opcode);
1498 tmpInst.addOperand(MCOperand::createReg(Reg0));
1499 tmpInst.setLoc(IDLoc);
1500 Instructions.push_back(tmpInst);
1501}
1502
1503void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1504 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1505 MCInst tmpInst;
1506 tmpInst.setOpcode(Opcode);
1507 tmpInst.addOperand(MCOperand::createReg(Reg0));
1508 tmpInst.addOperand(MCOperand::createReg(Reg1));
1509 tmpInst.addOperand(Op2);
1510 tmpInst.setLoc(IDLoc);
1511 Instructions.push_back(tmpInst);
1512}
1513
1514void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1515 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1516 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1517 Instructions);
1518}
1519
1520void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1521 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1522 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1523 Instructions);
1524}
1525
1526void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1527 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1528 if (ShiftAmount >= 32) {
1529 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1530 Instructions);
1531 return;
1532 }
1533
1534 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1535}
1536} // end anonymous namespace.
1537
Jack Carter9e65aa32013-03-22 00:05:30 +00001538bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001539 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001540 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001541 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001542
Jack Carter9e65aa32013-03-22 00:05:30 +00001543 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001544
1545 if (MCID.isBranch() || MCID.isCall()) {
1546 const unsigned Opcode = Inst.getOpcode();
1547 MCOperand Offset;
1548
1549 switch (Opcode) {
1550 default:
1551 break;
Kai Nackee0245392015-01-27 19:11:28 +00001552 case Mips::BBIT0:
1553 case Mips::BBIT032:
1554 case Mips::BBIT1:
1555 case Mips::BBIT132:
1556 assert(hasCnMips() && "instruction only valid for octeon cpus");
1557 // Fall through
1558
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001559 case Mips::BEQ:
1560 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001561 case Mips::BEQ_MM:
1562 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001563 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001564 Offset = Inst.getOperand(2);
1565 if (!Offset.isImm())
1566 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001567 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001568 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001569 if (OffsetToAlignment(Offset.getImm(),
1570 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001571 return Error(IDLoc, "branch to misaligned address");
1572 break;
1573 case Mips::BGEZ:
1574 case Mips::BGTZ:
1575 case Mips::BLEZ:
1576 case Mips::BLTZ:
1577 case Mips::BGEZAL:
1578 case Mips::BLTZAL:
1579 case Mips::BC1F:
1580 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001581 case Mips::BGEZ_MM:
1582 case Mips::BGTZ_MM:
1583 case Mips::BLEZ_MM:
1584 case Mips::BLTZ_MM:
1585 case Mips::BGEZAL_MM:
1586 case Mips::BLTZAL_MM:
1587 case Mips::BC1F_MM:
1588 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001589 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001590 Offset = Inst.getOperand(1);
1591 if (!Offset.isImm())
1592 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001593 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001594 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001595 if (OffsetToAlignment(Offset.getImm(),
1596 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001597 return Error(IDLoc, "branch to misaligned address");
1598 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001599 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001600 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001601 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001602 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001603 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1604 Offset = Inst.getOperand(1);
1605 if (!Offset.isImm())
1606 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001607 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001608 return Error(IDLoc, "branch target out of range");
1609 if (OffsetToAlignment(Offset.getImm(), 2LL))
1610 return Error(IDLoc, "branch to misaligned address");
1611 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001612 }
1613 }
1614
Daniel Sandersa84989a2014-06-16 13:25:35 +00001615 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1616 // We still accept it but it is a normal nop.
1617 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1618 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1619 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1620 "nop instruction");
1621 }
1622
Kai Nackee0245392015-01-27 19:11:28 +00001623 if (hasCnMips()) {
1624 const unsigned Opcode = Inst.getOpcode();
1625 MCOperand Opnd;
1626 int Imm;
1627
1628 switch (Opcode) {
1629 default:
1630 break;
1631
1632 case Mips::BBIT0:
1633 case Mips::BBIT032:
1634 case Mips::BBIT1:
1635 case Mips::BBIT132:
1636 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1637 // The offset is handled above
1638 Opnd = Inst.getOperand(1);
1639 if (!Opnd.isImm())
1640 return Error(IDLoc, "expected immediate operand kind");
1641 Imm = Opnd.getImm();
1642 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1643 Opcode == Mips::BBIT1 ? 63 : 31))
1644 return Error(IDLoc, "immediate operand value out of range");
1645 if (Imm > 31) {
1646 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1647 : Mips::BBIT132);
1648 Inst.getOperand(1).setImm(Imm - 32);
1649 }
1650 break;
1651
Kai Nackee0245392015-01-27 19:11:28 +00001652 case Mips::SEQi:
1653 case Mips::SNEi:
1654 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1655 Opnd = Inst.getOperand(2);
1656 if (!Opnd.isImm())
1657 return Error(IDLoc, "expected immediate operand kind");
1658 Imm = Opnd.getImm();
1659 if (!isInt<10>(Imm))
1660 return Error(IDLoc, "immediate operand value out of range");
1661 break;
1662 }
1663 }
1664
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001665 // This expansion is not in a function called by tryExpandInstruction()
1666 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001667 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1668 inPicMode()) {
1669 warnIfNoMacro(IDLoc);
1670
1671 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1672
1673 // We can do this expansion if there's only 1 symbol in the argument
1674 // expression.
1675 if (countMCSymbolRefExpr(JalExpr) > 1)
1676 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1677
1678 // FIXME: This is checking the expression can be handled by the later stages
1679 // of the assembler. We ought to leave it to those later stages but
1680 // we can't do that until we stop evaluateRelocExpr() rewriting the
1681 // expressions into non-equivalent forms.
1682 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1683
1684 // FIXME: Add support for label+offset operands (currently causes an error).
1685 // FIXME: Add support for forward-declared local symbols.
1686 // FIXME: Add expansion for when the LargeGOT option is enabled.
1687 if (JalSym->isInSection() || JalSym->isTemporary()) {
1688 if (isABI_O32()) {
1689 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001690 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001691 // R_(MICRO)MIPS_GOT16 label
1692 // addiu $25, $25, 0
1693 // R_(MICRO)MIPS_LO16 label
1694 // jalr $25
1695 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1696 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1697
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001698 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1699 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1700 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1701 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001702 } else if (isABI_N32() || isABI_N64()) {
1703 // If it's a local symbol and the N32/N64 ABIs are being used,
1704 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001705 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001706 // R_(MICRO)MIPS_GOT_DISP label
1707 // jalr $25
1708 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1709
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001710 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1711 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001712 }
1713 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001714 // If it's an external/weak symbol, we expand to:
1715 // lw/ld $25, 0($gp)
1716 // R_(MICRO)MIPS_CALL16 label
1717 // jalr $25
1718 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001719
Daniel Sandersb7002032015-11-20 13:16:35 +00001720 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1721 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001722 }
1723
1724 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001725 if (IsCpRestoreSet && inMicroMipsMode())
1726 JalrInst.setOpcode(Mips::JALRS_MM);
1727 else
1728 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001729 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1730 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1731
1732 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1733 // This relocation is supposed to be an optimization hint for the linker
1734 // and is not necessary for correctness.
1735
1736 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001737 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001738 }
1739
Jack Carter9e65aa32013-03-22 00:05:30 +00001740 if (MCID.mayLoad() || MCID.mayStore()) {
1741 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001742 // reference or immediate we may have to expand instructions.
1743 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001744 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001745 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1746 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001747 MCOperand &Op = Inst.getOperand(i);
1748 if (Op.isImm()) {
1749 int MemOffset = Op.getImm();
1750 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001751 // Offset can't exceed 16bit value.
1752 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001753 return false;
1754 }
1755 } else if (Op.isExpr()) {
1756 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001757 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001758 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001759 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001760 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001761 // Expand symbol.
1762 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001763 return false;
1764 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001765 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001766 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001767 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001768 }
1769 }
1770 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001771 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001772 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001773
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001774 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001775 if (MCID.mayLoad()) {
1776 // Try to create 16-bit GP relative load instruction.
1777 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1778 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1779 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1780 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1781 MCOperand &Op = Inst.getOperand(i);
1782 if (Op.isImm()) {
1783 int MemOffset = Op.getImm();
1784 MCOperand &DstReg = Inst.getOperand(0);
1785 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001786 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001787 getContext().getRegisterInfo()->getRegClass(
1788 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001789 (BaseReg.getReg() == Mips::GP ||
1790 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001791
1792 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1793 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001794 return false;
1795 }
1796 }
1797 }
1798 } // for
1799 } // if load
1800
1801 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1802
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001803 MCOperand Opnd;
1804 int Imm;
1805
1806 switch (Inst.getOpcode()) {
1807 default:
1808 break;
1809 case Mips::ADDIUS5_MM:
1810 Opnd = Inst.getOperand(2);
1811 if (!Opnd.isImm())
1812 return Error(IDLoc, "expected immediate operand kind");
1813 Imm = Opnd.getImm();
1814 if (Imm < -8 || Imm > 7)
1815 return Error(IDLoc, "immediate operand value out of range");
1816 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001817 case Mips::ADDIUSP_MM:
1818 Opnd = Inst.getOperand(0);
1819 if (!Opnd.isImm())
1820 return Error(IDLoc, "expected immediate operand kind");
1821 Imm = Opnd.getImm();
1822 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1823 Imm % 4 != 0)
1824 return Error(IDLoc, "immediate operand value out of range");
1825 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001826 case Mips::SLL16_MM:
1827 case Mips::SRL16_MM:
1828 Opnd = Inst.getOperand(2);
1829 if (!Opnd.isImm())
1830 return Error(IDLoc, "expected immediate operand kind");
1831 Imm = Opnd.getImm();
1832 if (Imm < 1 || Imm > 8)
1833 return Error(IDLoc, "immediate operand value out of range");
1834 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001835 case Mips::LI16_MM:
1836 Opnd = Inst.getOperand(1);
1837 if (!Opnd.isImm())
1838 return Error(IDLoc, "expected immediate operand kind");
1839 Imm = Opnd.getImm();
1840 if (Imm < -1 || Imm > 126)
1841 return Error(IDLoc, "immediate operand value out of range");
1842 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001843 case Mips::ADDIUR2_MM:
1844 Opnd = Inst.getOperand(2);
1845 if (!Opnd.isImm())
1846 return Error(IDLoc, "expected immediate operand kind");
1847 Imm = Opnd.getImm();
1848 if (!(Imm == 1 || Imm == -1 ||
1849 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1850 return Error(IDLoc, "immediate operand value out of range");
1851 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001852 case Mips::ADDIUR1SP_MM:
1853 Opnd = Inst.getOperand(1);
1854 if (!Opnd.isImm())
1855 return Error(IDLoc, "expected immediate operand kind");
1856 Imm = Opnd.getImm();
1857 if (OffsetToAlignment(Imm, 4LL))
1858 return Error(IDLoc, "misaligned immediate operand value");
1859 if (Imm < 0 || Imm > 255)
1860 return Error(IDLoc, "immediate operand value out of range");
1861 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001862 case Mips::ANDI16_MM:
1863 Opnd = Inst.getOperand(2);
1864 if (!Opnd.isImm())
1865 return Error(IDLoc, "expected immediate operand kind");
1866 Imm = Opnd.getImm();
1867 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1868 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1869 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1870 return Error(IDLoc, "immediate operand value out of range");
1871 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001872 case Mips::LBU16_MM:
1873 Opnd = Inst.getOperand(2);
1874 if (!Opnd.isImm())
1875 return Error(IDLoc, "expected immediate operand kind");
1876 Imm = Opnd.getImm();
1877 if (Imm < -1 || Imm > 14)
1878 return Error(IDLoc, "immediate operand value out of range");
1879 break;
1880 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001881 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001882 Opnd = Inst.getOperand(2);
1883 if (!Opnd.isImm())
1884 return Error(IDLoc, "expected immediate operand kind");
1885 Imm = Opnd.getImm();
1886 if (Imm < 0 || Imm > 15)
1887 return Error(IDLoc, "immediate operand value out of range");
1888 break;
1889 case Mips::LHU16_MM:
1890 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001891 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001892 Opnd = Inst.getOperand(2);
1893 if (!Opnd.isImm())
1894 return Error(IDLoc, "expected immediate operand kind");
1895 Imm = Opnd.getImm();
1896 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1897 return Error(IDLoc, "immediate operand value out of range");
1898 break;
1899 case Mips::LW16_MM:
1900 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001901 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001902 Opnd = Inst.getOperand(2);
1903 if (!Opnd.isImm())
1904 return Error(IDLoc, "expected immediate operand kind");
1905 Imm = Opnd.getImm();
1906 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1907 return Error(IDLoc, "immediate operand value out of range");
1908 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001909 case Mips::ADDIUPC_MM:
1910 MCOperand Opnd = Inst.getOperand(1);
1911 if (!Opnd.isImm())
1912 return Error(IDLoc, "expected immediate operand kind");
1913 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001914 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001915 return Error(IDLoc, "immediate operand value out of range");
1916 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001917 }
1918 }
1919
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001920 MacroExpanderResultTy ExpandResult =
1921 tryExpandInstruction(Inst, IDLoc, Instructions);
1922 switch (ExpandResult) {
1923 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001924 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001925 break;
1926 case MER_Success:
1927 break;
1928 case MER_Fail:
1929 return true;
1930 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001931
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001932 // If this instruction has a delay slot and .set reorder is active,
1933 // emit a NOP after it.
1934 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1935 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1936
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001937 if ((Inst.getOpcode() == Mips::JalOneReg ||
1938 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1939 isPicAndNotNxxAbi()) {
1940 if (IsCpRestoreSet) {
1941 // We need a NOP between the JALR and the LW:
1942 // If .set reorder has been used, we've already emitted a NOP.
1943 // If .set noreorder has been used, we need to emit a NOP at this point.
1944 if (!AssemblerOptions.back()->isReorder())
1945 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1946
1947 // Load the $gp from the stack.
1948 SmallVector<MCInst, 3> LoadInsts;
1949 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1950 IDLoc, LoadInsts);
1951
1952 for (const MCInst &Inst : LoadInsts)
1953 Instructions.push_back(Inst);
1954
1955 } else
1956 Warning(IDLoc, "no .cprestore used in PIC mode");
1957 }
1958
Jack Carter9e65aa32013-03-22 00:05:30 +00001959 return false;
1960}
1961
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001962MipsAsmParser::MacroExpanderResultTy
1963MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1964 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001965 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001966 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001967 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001968 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001969 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1970 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001971 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001972 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1973 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001974 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001975 case Mips::LoadAddrImm64:
1976 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1977 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1978 "expected immediate operand kind");
1979
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001980 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1981 Inst.getOperand(1),
1982 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1983 Instructions)
1984 ? MER_Fail
1985 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001986 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001987 case Mips::LoadAddrReg64:
1988 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1989 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1990 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1991 "expected immediate operand kind");
1992
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001993 return expandLoadAddress(Inst.getOperand(0).getReg(),
1994 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1995 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
1996 Instructions)
1997 ? MER_Fail
1998 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001999 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002000 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002001 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
2002 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002003 case Mips::SWM_MM:
2004 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002005 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
2006 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002007 case Mips::JalOneReg:
2008 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002009 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
2010 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002011 case Mips::BneImm:
2012 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002013 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002014 case Mips::BLT:
2015 case Mips::BLE:
2016 case Mips::BGE:
2017 case Mips::BGT:
2018 case Mips::BLTU:
2019 case Mips::BLEU:
2020 case Mips::BGEU:
2021 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002022 case Mips::BLTL:
2023 case Mips::BLEL:
2024 case Mips::BGEL:
2025 case Mips::BGTL:
2026 case Mips::BLTUL:
2027 case Mips::BLEUL:
2028 case Mips::BGEUL:
2029 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002030 case Mips::BLTImmMacro:
2031 case Mips::BLEImmMacro:
2032 case Mips::BGEImmMacro:
2033 case Mips::BGTImmMacro:
2034 case Mips::BLTUImmMacro:
2035 case Mips::BLEUImmMacro:
2036 case Mips::BGEUImmMacro:
2037 case Mips::BGTUImmMacro:
2038 case Mips::BLTLImmMacro:
2039 case Mips::BLELImmMacro:
2040 case Mips::BGELImmMacro:
2041 case Mips::BGTLImmMacro:
2042 case Mips::BLTULImmMacro:
2043 case Mips::BLEULImmMacro:
2044 case Mips::BGEULImmMacro:
2045 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002046 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2047 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002048 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002049 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2050 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002051 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002052 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2053 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002054 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002055 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2056 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002057 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002058 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2059 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002060 case Mips::PseudoTRUNC_W_S:
2061 return expandTrunc(Inst, false, false, IDLoc, Instructions) ? MER_Fail
2062 : MER_Success;
2063 case Mips::PseudoTRUNC_W_D32:
2064 return expandTrunc(Inst, true, false, IDLoc, Instructions) ? MER_Fail
2065 : MER_Success;
2066 case Mips::PseudoTRUNC_W_D:
2067 return expandTrunc(Inst, true, true, IDLoc, Instructions) ? MER_Fail
2068 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002069 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002070 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002071 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002072 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002073 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002074 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2075 case Mips::NORImm:
2076 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2077 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002078 case Mips::ADDi:
2079 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002080 case Mips::SLTi:
2081 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002082 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2083 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2084 int64_t ImmValue = Inst.getOperand(2).getImm();
2085 if (isInt<16>(ImmValue))
2086 return MER_NotAMacro;
2087 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2088 : MER_Success;
2089 }
2090 return MER_NotAMacro;
2091 case Mips::ANDi:
2092 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002093 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002094 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2095 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2096 int64_t ImmValue = Inst.getOperand(2).getImm();
2097 if (isUInt<16>(ImmValue))
2098 return MER_NotAMacro;
2099 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2100 : MER_Success;
2101 }
2102 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002103 case Mips::ROL:
2104 case Mips::ROR:
2105 return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail
2106 : MER_Success;
2107 case Mips::ROLImm:
2108 case Mips::RORImm:
2109 return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2110 : MER_Success;
2111 case Mips::DROL:
2112 case Mips::DROR:
2113 return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail
2114 : MER_Success;
2115 case Mips::DROLImm:
2116 case Mips::DRORImm:
2117 return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2118 : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002119 case Mips::ABSMacro:
2120 return expandAbs(Inst, IDLoc, Instructions) ? MER_Fail
2121 : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002122 }
Jack Carter30a59822012-10-04 04:03:53 +00002123}
Jack Carter92995f12012-10-06 00:53:28 +00002124
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002125bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2126 SmallVectorImpl<MCInst> &Instructions) {
2127 // Create a JALR instruction which is going to replace the pseudo-JAL.
2128 MCInst JalrInst;
2129 JalrInst.setLoc(IDLoc);
2130 const MCOperand FirstRegOp = Inst.getOperand(0);
2131 const unsigned Opcode = Inst.getOpcode();
2132
2133 if (Opcode == Mips::JalOneReg) {
2134 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002135 if (IsCpRestoreSet && inMicroMipsMode()) {
2136 JalrInst.setOpcode(Mips::JALRS16_MM);
2137 JalrInst.addOperand(FirstRegOp);
2138 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002139 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002140 JalrInst.addOperand(FirstRegOp);
2141 } else {
2142 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002143 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002144 JalrInst.addOperand(FirstRegOp);
2145 }
2146 } else if (Opcode == Mips::JalTwoReg) {
2147 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002148 if (IsCpRestoreSet && inMicroMipsMode())
2149 JalrInst.setOpcode(Mips::JALRS_MM);
2150 else
2151 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002152 JalrInst.addOperand(FirstRegOp);
2153 const MCOperand SecondRegOp = Inst.getOperand(1);
2154 JalrInst.addOperand(SecondRegOp);
2155 }
2156 Instructions.push_back(JalrInst);
2157
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002158 // If .set reorder is active and branch instruction has a delay slot,
2159 // emit a NOP after it.
2160 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2161 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002162 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002163 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002164
2165 return false;
2166}
2167
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002168/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002169template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002170 unsigned BitNum = findFirstSet(x);
2171
2172 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2173}
2174
2175/// Load (or add) an immediate into a register.
2176///
2177/// @param ImmValue The immediate to load.
2178/// @param DstReg The register that will hold the immediate.
2179/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2180/// for a simple initialization.
2181/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2182/// @param IsAddress True if the immediate represents an address. False if it
2183/// is an integer.
2184/// @param IDLoc Location of the immediate in the source file.
2185/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002186bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002187 unsigned SrcReg, bool Is32BitImm,
2188 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002189 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002190 if (!Is32BitImm && !isGP64bit()) {
2191 Error(IDLoc, "instruction requires a 64-bit architecture");
2192 return true;
2193 }
2194
Daniel Sanders03f9c012015-07-14 12:24:22 +00002195 if (Is32BitImm) {
2196 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2197 // Sign extend up to 64-bit so that the predicates match the hardware
2198 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2199 // true.
2200 ImmValue = SignExtend64<32>(ImmValue);
2201 } else {
2202 Error(IDLoc, "instruction requires a 32-bit immediate");
2203 return true;
2204 }
2205 }
2206
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002207 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2208 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2209
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002210 bool UseSrcReg = false;
2211 if (SrcReg != Mips::NoRegister)
2212 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002213
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002214 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002215 if (UseSrcReg &&
2216 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002217 // At this point we need AT to perform the expansions and we exit if it is
2218 // not available.
2219 unsigned ATReg = getATReg(IDLoc);
2220 if (!ATReg)
2221 return true;
2222 TmpReg = ATReg;
2223 }
2224
Daniel Sanders03f9c012015-07-14 12:24:22 +00002225 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002226 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002227 SrcReg = ZeroReg;
2228
2229 // This doesn't quite follow the usual ABI expectations for N32 but matches
2230 // traditional assembler behaviour. N32 would normally use addiu for both
2231 // integers and addresses.
2232 if (IsAddress && !Is32BitImm) {
2233 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2234 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002235 }
2236
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002237 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2238 return false;
2239 }
2240
2241 if (isUInt<16>(ImmValue)) {
2242 unsigned TmpReg = DstReg;
2243 if (SrcReg == DstReg) {
2244 TmpReg = getATReg(IDLoc);
2245 if (!TmpReg)
2246 return true;
2247 }
2248
2249 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002250 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002251 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2252 return false;
2253 }
2254
2255 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002256 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002257
Toma Tabacu79588102015-04-29 10:19:56 +00002258 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2259 uint16_t Bits15To0 = ImmValue & 0xffff;
2260
Toma Tabacua3d056f2015-05-15 09:42:11 +00002261 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002262 // Traditional behaviour seems to special case this particular value. It's
2263 // not clear why other masks are handled differently.
2264 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002265 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002266 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2267 if (UseSrcReg)
2268 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2269 return false;
2270 }
2271
2272 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002273 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002274 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002275 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002276 if (Bits15To0)
2277 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2278 if (UseSrcReg)
2279 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2280 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002281 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002282
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002283 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2284 if (Bits15To0)
2285 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002286 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002287 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2288 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002289 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002290
2291 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2292 if (Is32BitImm) {
2293 Error(IDLoc, "instruction requires a 32-bit immediate");
2294 return true;
2295 }
2296
2297 // Traditionally, these immediates are shifted as little as possible and as
2298 // such we align the most significant bit to bit 15 of our temporary.
2299 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2300 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2301 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2302 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2303 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2304 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2305
2306 if (UseSrcReg)
2307 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2308
2309 return false;
2310 }
2311
2312 warnIfNoMacro(IDLoc);
2313
2314 // The remaining case is packed with a sequence of dsll and ori with zeros
2315 // being omitted and any neighbouring dsll's being coalesced.
2316 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2317
2318 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2319 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2320 IDLoc, Instructions))
2321 return false;
2322
2323 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2324 // skip it and defer the shift to the next chunk.
2325 unsigned ShiftCarriedForwards = 16;
2326 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2327 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2328
2329 if (ImmChunk != 0) {
2330 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2331 Instructions);
2332 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2333 ShiftCarriedForwards = 0;
2334 }
2335
2336 ShiftCarriedForwards += 16;
2337 }
2338 ShiftCarriedForwards -= 16;
2339
2340 // Finish any remaining shifts left by trailing zeros.
2341 if (ShiftCarriedForwards)
2342 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2343 Instructions);
2344
2345 if (UseSrcReg)
2346 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2347
Matheus Almeida3813d572014-06-19 14:39:14 +00002348 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002349}
Jack Carter92995f12012-10-06 00:53:28 +00002350
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002351bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2352 SmallVectorImpl<MCInst> &Instructions) {
2353 const MCOperand &ImmOp = Inst.getOperand(1);
2354 assert(ImmOp.isImm() && "expected immediate operand kind");
2355 const MCOperand &DstRegOp = Inst.getOperand(0);
2356 assert(DstRegOp.isReg() && "expected register operand kind");
2357
2358 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002359 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002360 return true;
2361
2362 return false;
2363}
2364
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002365bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2366 const MCOperand &Offset,
2367 bool Is32BitAddress, SMLoc IDLoc,
2368 SmallVectorImpl<MCInst> &Instructions) {
2369 // la can't produce a usable address when addresses are 64-bit.
2370 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2371 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2372 // We currently can't do this because we depend on the equality
2373 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2374 Error(IDLoc, "la used to load 64-bit address");
2375 // Continue as if we had 'dla' instead.
2376 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002377 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002378
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002379 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002380 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002381 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002382 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002383 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002384
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002385 if (!Offset.isImm())
2386 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2387 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002388
Scott Egerton24557012016-01-21 15:11:01 +00002389 if (!ABI.ArePtrs64bit()) {
2390 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2391 Is32BitAddress = true;
2392 }
2393
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002394 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2395 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002396}
2397
Toma Tabacuf712ede2015-06-17 14:31:51 +00002398bool MipsAsmParser::loadAndAddSymbolAddress(
2399 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2400 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002401 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002402
Daniel Sandersd5a89412015-10-05 13:19:29 +00002403 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2404 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2405 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2406 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2407 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002408
Toma Tabacufb9d1252015-06-22 12:08:39 +00002409 bool UseSrcReg = SrcReg != Mips::NoRegister;
2410
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002411 // This is the 64-bit symbol address expansion.
2412 if (ABI.ArePtrs64bit() && isGP64bit()) {
2413 // We always need AT for the 64-bit expansion.
2414 // If it is not available we exit.
2415 unsigned ATReg = getATReg(IDLoc);
2416 if (!ATReg)
2417 return true;
2418
Daniel Sandersd5a89412015-10-05 13:19:29 +00002419 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2420 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2421 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2422 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002423
Scott Egerton24557012016-01-21 15:11:01 +00002424 if (UseSrcReg &&
2425 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2426 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002427 // If $rs is the same as $rd:
2428 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2429 // daddiu $at, $at, %higher(sym)
2430 // dsll $at, $at, 16
2431 // daddiu $at, $at, %hi(sym)
2432 // dsll $at, $at, 16
2433 // daddiu $at, $at, %lo(sym)
2434 // daddu $rd, $at, $rd
2435 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2436 Instructions);
2437 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2438 IDLoc, Instructions);
2439 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2440 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2441 Instructions);
2442 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2443 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2444 Instructions);
2445 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2446
2447 return false;
2448 }
2449
2450 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2451 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2452 // lui $at, %hi(sym)
2453 // daddiu $rd, $rd, %higher(sym)
2454 // daddiu $at, $at, %lo(sym)
2455 // dsll32 $rd, $rd, 0
2456 // daddu $rd, $rd, $at
2457 // (daddu $rd, $rd, $rs)
2458 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2459 Instructions);
2460 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2461 Instructions);
2462 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2463 IDLoc, Instructions);
2464 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2465 Instructions);
2466 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2467 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2468 if (UseSrcReg)
2469 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2470
2471 return false;
2472 }
2473
2474 // And now, the 32-bit symbol address expansion:
2475 // If $rs is the same as $rd:
2476 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2477 // ori $at, $at, %lo(sym)
2478 // addu $rd, $at, $rd
2479 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2480 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2481 // ori $rd, $rd, %lo(sym)
2482 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002483 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002484 if (UseSrcReg &&
2485 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002486 // If $rs is the same as $rd, we need to use AT.
2487 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002488 unsigned ATReg = getATReg(IDLoc);
2489 if (!ATReg)
2490 return true;
2491 TmpReg = ATReg;
2492 }
2493
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002494 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2495 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2496 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002497
Toma Tabacufb9d1252015-06-22 12:08:39 +00002498 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002499 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2500 else
Scott Egerton24557012016-01-21 15:11:01 +00002501 assert(
2502 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002503
Toma Tabacu674825c2015-06-16 12:16:24 +00002504 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002505}
2506
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002507bool MipsAsmParser::expandUncondBranchMMPseudo(
2508 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002509 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2510 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002511
2512 MCOperand Offset = Inst.getOperand(0);
2513 if (Offset.isExpr()) {
2514 Inst.clear();
2515 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002516 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2517 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2518 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002519 } else {
2520 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002521 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002522 // If offset fits into 11 bits then this instruction becomes microMIPS
2523 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002524 if (inMicroMipsMode())
2525 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002526 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002527 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002528 Error(IDLoc, "branch target out of range");
2529 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2530 Error(IDLoc, "branch to misaligned address");
2531 Inst.clear();
2532 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002533 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2534 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2535 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002536 }
2537 }
2538 Instructions.push_back(Inst);
2539
Zoran Jovanovicada70912015-09-07 11:56:37 +00002540 // If .set reorder is active and branch instruction has a delay slot,
2541 // emit a NOP after it.
2542 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2543 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002544 createNop(true, IDLoc, Instructions);
2545
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002546 return false;
2547}
2548
Toma Tabacue1e460d2015-06-11 10:36:10 +00002549bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2550 SmallVectorImpl<MCInst> &Instructions) {
2551 const MCOperand &DstRegOp = Inst.getOperand(0);
2552 assert(DstRegOp.isReg() && "expected register operand kind");
2553
2554 const MCOperand &ImmOp = Inst.getOperand(1);
2555 assert(ImmOp.isImm() && "expected immediate operand kind");
2556
2557 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2558 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2559
2560 unsigned OpCode = 0;
2561 switch(Inst.getOpcode()) {
2562 case Mips::BneImm:
2563 OpCode = Mips::BNE;
2564 break;
2565 case Mips::BeqImm:
2566 OpCode = Mips::BEQ;
2567 break;
2568 default:
2569 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2570 break;
2571 }
2572
2573 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002574 if (ImmValue == 0)
2575 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2576 Instructions);
2577 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002578 warnIfNoMacro(IDLoc);
2579
2580 unsigned ATReg = getATReg(IDLoc);
2581 if (!ATReg)
2582 return true;
2583
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002584 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2585 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002586 return true;
2587
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002588 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002589 }
2590 return false;
2591}
2592
Jack Carter9e65aa32013-03-22 00:05:30 +00002593void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002594 SmallVectorImpl<MCInst> &Instructions,
2595 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002596 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002597 const MCExpr *ExprOffset;
2598 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002599 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002600 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2601 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002602 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002603 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2604 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002605 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002606 if (isImmOpnd) {
2607 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2608 ImmOffset = Inst.getOperand(2).getImm();
2609 LoOffset = ImmOffset & 0x0000ffff;
2610 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002611 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002612 if (LoOffset & 0x8000)
2613 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002614 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002615 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002616 // These are some of the types of expansions we perform here:
2617 // 1) lw $8, sym => lui $8, %hi(sym)
2618 // lw $8, %lo(sym)($8)
2619 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2620 // add $8, $8, $9
2621 // lw $8, %lo(offset)($9)
2622 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2623 // add $at, $at, $8
2624 // lw $8, %lo(offset)($at)
2625 // 4) sw $8, sym => lui $at, %hi(sym)
2626 // sw $8, %lo(sym)($at)
2627 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2628 // add $at, $at, $8
2629 // sw $8, %lo(offset)($at)
2630 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2631 // ldc1 $f0, %lo(sym)($at)
2632 //
2633 // For load instructions we can use the destination register as a temporary
2634 // if base and dst are different (examples 1 and 2) and if the base register
2635 // is general purpose otherwise we must use $at (example 6) and error if it's
2636 // not available. For stores we must use $at (examples 4 and 5) because we
2637 // must not clobber the source register setting up the offset.
2638 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2639 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2640 unsigned RegClassIDOp0 =
2641 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2642 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2643 (RegClassIDOp0 == Mips::GPR64RegClassID);
2644 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002645 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002646 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002647 // At this point we need AT to perform the expansions and we exit if it is
2648 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002649 TmpRegNum = getATReg(IDLoc);
2650 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002651 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002652 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002653
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002654 emitRX(Mips::LUi, TmpRegNum,
2655 isImmOpnd ? MCOperand::createImm(HiOffset)
2656 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2657 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002658 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002659 if (BaseRegNum != Mips::ZERO)
2660 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002661 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002662 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002663 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2664 isImmOpnd
2665 ? MCOperand::createImm(LoOffset)
2666 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2667 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002668}
2669
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002670bool
2671MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2672 SmallVectorImpl<MCInst> &Instructions) {
2673 unsigned OpNum = Inst.getNumOperands();
2674 unsigned Opcode = Inst.getOpcode();
2675 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2676
2677 assert (Inst.getOperand(OpNum - 1).isImm() &&
2678 Inst.getOperand(OpNum - 2).isReg() &&
2679 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2680
2681 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2682 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002683 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2684 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2685 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2686 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002687 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002688 if (inMicroMipsMode() && hasMips32r6())
2689 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2690 else
2691 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2692 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002693
2694 Inst.setOpcode(NewOpcode);
2695 Instructions.push_back(Inst);
2696 return false;
2697}
2698
Toma Tabacu1a108322015-06-17 13:20:24 +00002699bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2700 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002701 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002702 unsigned PseudoOpcode = Inst.getOpcode();
2703 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002704 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002705 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2706
2707 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002708 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002709
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002710 unsigned TrgReg;
2711 if (TrgOp.isReg())
2712 TrgReg = TrgOp.getReg();
2713 else if (TrgOp.isImm()) {
2714 warnIfNoMacro(IDLoc);
2715 EmittedNoMacroWarning = true;
2716
2717 TrgReg = getATReg(IDLoc);
2718 if (!TrgReg)
2719 return true;
2720
2721 switch(PseudoOpcode) {
2722 default:
2723 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2724 case Mips::BLTImmMacro:
2725 PseudoOpcode = Mips::BLT;
2726 break;
2727 case Mips::BLEImmMacro:
2728 PseudoOpcode = Mips::BLE;
2729 break;
2730 case Mips::BGEImmMacro:
2731 PseudoOpcode = Mips::BGE;
2732 break;
2733 case Mips::BGTImmMacro:
2734 PseudoOpcode = Mips::BGT;
2735 break;
2736 case Mips::BLTUImmMacro:
2737 PseudoOpcode = Mips::BLTU;
2738 break;
2739 case Mips::BLEUImmMacro:
2740 PseudoOpcode = Mips::BLEU;
2741 break;
2742 case Mips::BGEUImmMacro:
2743 PseudoOpcode = Mips::BGEU;
2744 break;
2745 case Mips::BGTUImmMacro:
2746 PseudoOpcode = Mips::BGTU;
2747 break;
2748 case Mips::BLTLImmMacro:
2749 PseudoOpcode = Mips::BLTL;
2750 break;
2751 case Mips::BLELImmMacro:
2752 PseudoOpcode = Mips::BLEL;
2753 break;
2754 case Mips::BGELImmMacro:
2755 PseudoOpcode = Mips::BGEL;
2756 break;
2757 case Mips::BGTLImmMacro:
2758 PseudoOpcode = Mips::BGTL;
2759 break;
2760 case Mips::BLTULImmMacro:
2761 PseudoOpcode = Mips::BLTUL;
2762 break;
2763 case Mips::BLEULImmMacro:
2764 PseudoOpcode = Mips::BLEUL;
2765 break;
2766 case Mips::BGEULImmMacro:
2767 PseudoOpcode = Mips::BGEUL;
2768 break;
2769 case Mips::BGTULImmMacro:
2770 PseudoOpcode = Mips::BGTUL;
2771 break;
2772 }
2773
2774 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2775 false, IDLoc, Instructions))
2776 return true;
2777 }
2778
Toma Tabacu1a108322015-06-17 13:20:24 +00002779 switch (PseudoOpcode) {
2780 case Mips::BLT:
2781 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002782 case Mips::BLTL:
2783 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002784 AcceptsEquality = false;
2785 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002786 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2787 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002788 ZeroSrcOpcode = Mips::BGTZ;
2789 ZeroTrgOpcode = Mips::BLTZ;
2790 break;
2791 case Mips::BLE:
2792 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002793 case Mips::BLEL:
2794 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002795 AcceptsEquality = true;
2796 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002797 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2798 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002799 ZeroSrcOpcode = Mips::BGEZ;
2800 ZeroTrgOpcode = Mips::BLEZ;
2801 break;
2802 case Mips::BGE:
2803 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002804 case Mips::BGEL:
2805 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002806 AcceptsEquality = true;
2807 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002808 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2809 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002810 ZeroSrcOpcode = Mips::BLEZ;
2811 ZeroTrgOpcode = Mips::BGEZ;
2812 break;
2813 case Mips::BGT:
2814 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002815 case Mips::BGTL:
2816 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002817 AcceptsEquality = false;
2818 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002819 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2820 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002821 ZeroSrcOpcode = Mips::BLTZ;
2822 ZeroTrgOpcode = Mips::BGTZ;
2823 break;
2824 default:
2825 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2826 }
2827
Toma Tabacu1a108322015-06-17 13:20:24 +00002828 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2829 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2830 if (IsSrcRegZero && IsTrgRegZero) {
2831 // FIXME: All of these Opcode-specific if's are needed for compatibility
2832 // with GAS' behaviour. However, they may not generate the most efficient
2833 // code in some circumstances.
2834 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002835 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2836 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002837 return false;
2838 }
2839 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002840 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2841 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002842 Warning(IDLoc, "branch is always taken");
2843 return false;
2844 }
2845 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002846 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2847 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002848 Warning(IDLoc, "branch is always taken");
2849 return false;
2850 }
2851 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002852 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2853 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002854 return false;
2855 }
2856 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002857 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2858 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002859 return false;
2860 }
2861 if (AcceptsEquality) {
2862 // If both registers are $0 and the pseudo-branch accepts equality, it
2863 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002864 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2865 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002866 Warning(IDLoc, "branch is always taken");
2867 return false;
2868 }
2869 // If both registers are $0 and the pseudo-branch does not accept
2870 // equality, it will never be taken, so we don't have to emit anything.
2871 return false;
2872 }
2873 if (IsSrcRegZero || IsTrgRegZero) {
2874 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2875 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2876 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2877 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2878 // the pseudo-branch will never be taken, so we don't emit anything.
2879 // This only applies to unsigned pseudo-branches.
2880 return false;
2881 }
2882 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2883 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2884 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2885 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2886 // the pseudo-branch will always be taken, so we emit an unconditional
2887 // branch.
2888 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002889 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2890 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002891 Warning(IDLoc, "branch is always taken");
2892 return false;
2893 }
2894 if (IsUnsigned) {
2895 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2896 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2897 // the pseudo-branch will be taken only when the non-zero register is
2898 // different from 0, so we emit a BNEZ.
2899 //
2900 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2901 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2902 // the pseudo-branch will be taken only when the non-zero register is
2903 // equal to 0, so we emit a BEQZ.
2904 //
2905 // Because only BLEU and BGEU branch on equality, we can use the
2906 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002907 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2908 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2909 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002910 return false;
2911 }
2912 // If we have a signed pseudo-branch and one of the registers is $0,
2913 // we can use an appropriate compare-to-zero branch. We select which one
2914 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002915 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2916 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2917 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002918 return false;
2919 }
2920
2921 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2922 // expansions. If it is not available, we return.
2923 unsigned ATRegNum = getATReg(IDLoc);
2924 if (!ATRegNum)
2925 return true;
2926
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002927 if (!EmittedNoMacroWarning)
2928 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002929
2930 // SLT fits well with 2 of our 4 pseudo-branches:
2931 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2932 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2933 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2934 // This is accomplished by using a BNEZ with the result of the SLT.
2935 //
2936 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2937 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2938 // Because only BGE and BLE branch on equality, we can use the
2939 // AcceptsEquality variable to decide when to emit the BEQZ.
2940 // Note that the order of the SLT arguments doesn't change between
2941 // opposites.
2942 //
2943 // The same applies to the unsigned variants, except that SLTu is used
2944 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002945 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2946 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2947 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002948
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002949 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2950 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2951 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2952 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002953 return false;
2954}
2955
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002956bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2957 SmallVectorImpl<MCInst> &Instructions,
2958 const bool IsMips64, const bool Signed) {
2959 if (hasMips32r6()) {
2960 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2961 return false;
2962 }
2963
2964 warnIfNoMacro(IDLoc);
2965
2966 const MCOperand &RsRegOp = Inst.getOperand(0);
2967 assert(RsRegOp.isReg() && "expected register operand kind");
2968 unsigned RsReg = RsRegOp.getReg();
2969
2970 const MCOperand &RtRegOp = Inst.getOperand(1);
2971 assert(RtRegOp.isReg() && "expected register operand kind");
2972 unsigned RtReg = RtRegOp.getReg();
2973 unsigned DivOp;
2974 unsigned ZeroReg;
2975
2976 if (IsMips64) {
2977 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2978 ZeroReg = Mips::ZERO_64;
2979 } else {
2980 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2981 ZeroReg = Mips::ZERO;
2982 }
2983
2984 bool UseTraps = useTraps();
2985
2986 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2987 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2988 Warning(IDLoc, "dividing zero by zero");
2989 if (IsMips64) {
2990 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2991 if (UseTraps) {
2992 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2993 return false;
2994 }
2995
2996 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2997 return false;
2998 }
2999 } else {
3000 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3001 return false;
3002 }
3003 }
3004
3005 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3006 Warning(IDLoc, "division by zero");
3007 if (Signed) {
3008 if (UseTraps) {
3009 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3010 return false;
3011 }
3012
3013 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3014 return false;
3015 }
3016 }
3017
3018 // FIXME: The values for these two BranchTarget variables may be different in
3019 // micromips. These magic numbers need to be removed.
3020 unsigned BranchTargetNoTraps;
3021 unsigned BranchTarget;
3022
3023 if (UseTraps) {
3024 BranchTarget = IsMips64 ? 12 : 8;
3025 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3026 } else {
3027 BranchTarget = IsMips64 ? 20 : 16;
3028 BranchTargetNoTraps = 8;
3029 // Branch to the li instruction.
3030 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
3031 Instructions);
3032 }
3033
3034 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3035
3036 if (!UseTraps)
3037 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3038
3039 if (!Signed) {
3040 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3041 return false;
3042 }
3043
3044 unsigned ATReg = getATReg(IDLoc);
3045 if (!ATReg)
3046 return true;
3047
3048 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
3049 if (IsMips64) {
3050 // Branch to the mflo instruction.
3051 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3052 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
3053 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
3054 } else {
3055 // Branch to the mflo instruction.
3056 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3057 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
3058 }
3059
3060 if (UseTraps)
3061 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3062 else {
3063 // Branch to the mflo instruction.
3064 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3065 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3066 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3067 }
3068 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3069 return false;
3070}
3071
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003072bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
3073 SMLoc IDLoc,
3074 SmallVectorImpl<MCInst> &Instructions) {
3075
3076 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3077 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3078 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3079
3080 unsigned FirstReg = Inst.getOperand(0).getReg();
3081 unsigned SecondReg = Inst.getOperand(1).getReg();
3082 unsigned ThirdReg = Inst.getOperand(2).getReg();
3083
3084 if (hasMips1() && !hasMips2()) {
3085 unsigned ATReg = getATReg(IDLoc);
3086 if (!ATReg)
3087 return true;
3088 emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, Instructions);
3089 emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, Instructions);
3090 createNop(false, IDLoc, Instructions);
3091 emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, Instructions);
3092 emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, Instructions);
3093 emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, Instructions);
3094 createNop(false, IDLoc, Instructions);
3095 emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3096 : Mips::CVT_W_S,
3097 FirstReg, SecondReg, IDLoc, Instructions);
3098 emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, Instructions);
3099 createNop(false, IDLoc, Instructions);
3100 return false;
3101 }
3102
3103 emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3104 : Mips::TRUNC_W_S,
3105 FirstReg, SecondReg, IDLoc, Instructions);
3106
3107 return false;
3108}
3109
Daniel Sanders6394ee52015-10-15 14:52:58 +00003110bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3111 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003112 if (hasMips32r6() || hasMips64r6()) {
3113 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3114 return false;
3115 }
3116
3117 warnIfNoMacro(IDLoc);
3118
3119 const MCOperand &DstRegOp = Inst.getOperand(0);
3120 assert(DstRegOp.isReg() && "expected register operand kind");
3121
3122 const MCOperand &SrcRegOp = Inst.getOperand(1);
3123 assert(SrcRegOp.isReg() && "expected register operand kind");
3124
3125 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3126 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3127
3128 unsigned DstReg = DstRegOp.getReg();
3129 unsigned SrcReg = SrcRegOp.getReg();
3130 int64_t OffsetValue = OffsetImmOp.getImm();
3131
3132 // NOTE: We always need AT for ULHU, as it is always used as the source
3133 // register for one of the LBu's.
3134 unsigned ATReg = getATReg(IDLoc);
3135 if (!ATReg)
3136 return true;
3137
3138 // When the value of offset+1 does not fit in 16 bits, we have to load the
3139 // offset in AT, (D)ADDu the original source register (if there was one), and
3140 // then use AT as the source register for the 2 generated LBu's.
3141 bool LoadedOffsetInAT = false;
3142 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3143 LoadedOffsetInAT = true;
3144
3145 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003146 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003147 return true;
3148
3149 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3150 // because it will make our output more similar to GAS'. For example,
3151 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3152 // instead of just an "ori $1, $9, 32768".
3153 // NOTE: If there is no source register specified in the ULHU, the parser
3154 // will interpret it as $0.
3155 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3156 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3157 }
3158
3159 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3160 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3161 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3162
3163 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3164 if (isLittle()) {
3165 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3166 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3167 } else {
3168 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3169 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3170 }
3171
3172 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3173
Daniel Sanders6394ee52015-10-15 14:52:58 +00003174 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3175 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003176
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003177 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3178 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003179
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003180 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003181
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003182 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003183
3184 return false;
3185}
3186
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003187bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3188 SmallVectorImpl<MCInst> &Instructions) {
3189 if (hasMips32r6() || hasMips64r6()) {
3190 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3191 return false;
3192 }
3193
3194 const MCOperand &DstRegOp = Inst.getOperand(0);
3195 assert(DstRegOp.isReg() && "expected register operand kind");
3196
3197 const MCOperand &SrcRegOp = Inst.getOperand(1);
3198 assert(SrcRegOp.isReg() && "expected register operand kind");
3199
3200 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3201 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3202
3203 unsigned SrcReg = SrcRegOp.getReg();
3204 int64_t OffsetValue = OffsetImmOp.getImm();
3205 unsigned ATReg = 0;
3206
3207 // When the value of offset+3 does not fit in 16 bits, we have to load the
3208 // offset in AT, (D)ADDu the original source register (if there was one), and
3209 // then use AT as the source register for the generated LWL and LWR.
3210 bool LoadedOffsetInAT = false;
3211 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3212 ATReg = getATReg(IDLoc);
3213 if (!ATReg)
3214 return true;
3215 LoadedOffsetInAT = true;
3216
3217 warnIfNoMacro(IDLoc);
3218
3219 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003220 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003221 return true;
3222
3223 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3224 // because it will make our output more similar to GAS'. For example,
3225 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3226 // instead of just an "ori $1, $9, 32768".
3227 // NOTE: If there is no source register specified in the ULW, the parser
3228 // will interpret it as $0.
3229 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3230 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3231 }
3232
3233 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3234 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3235 if (isLittle()) {
3236 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3237 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3238 } else {
3239 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3240 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3241 }
3242
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003243 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3244 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003245
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003246 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3247 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003248
3249 return false;
3250}
3251
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003252bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3253 SmallVectorImpl<MCInst> &Instructions) {
3254
3255 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3256 assert (Inst.getOperand(0).isReg() &&
3257 Inst.getOperand(1).isReg() &&
3258 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3259
3260 unsigned ATReg = Mips::NoRegister;
3261 unsigned FinalDstReg = Mips::NoRegister;
3262 unsigned DstReg = Inst.getOperand(0).getReg();
3263 unsigned SrcReg = Inst.getOperand(1).getReg();
3264 int64_t ImmValue = Inst.getOperand(2).getImm();
3265
3266 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3267
3268 unsigned FinalOpcode = Inst.getOpcode();
3269
3270 if (DstReg == SrcReg) {
3271 ATReg = getATReg(Inst.getLoc());
3272 if (!ATReg)
3273 return true;
3274 FinalDstReg = DstReg;
3275 DstReg = ATReg;
3276 }
3277
3278 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3279 switch (FinalOpcode) {
3280 default:
3281 llvm_unreachable("unimplemented expansion");
3282 case (Mips::ADDi):
3283 FinalOpcode = Mips::ADD;
3284 break;
3285 case (Mips::ADDiu):
3286 FinalOpcode = Mips::ADDu;
3287 break;
3288 case (Mips::ANDi):
3289 FinalOpcode = Mips::AND;
3290 break;
3291 case (Mips::NORImm):
3292 FinalOpcode = Mips::NOR;
3293 break;
3294 case (Mips::ORi):
3295 FinalOpcode = Mips::OR;
3296 break;
3297 case (Mips::SLTi):
3298 FinalOpcode = Mips::SLT;
3299 break;
3300 case (Mips::SLTiu):
3301 FinalOpcode = Mips::SLTu;
3302 break;
3303 case (Mips::XORi):
3304 FinalOpcode = Mips::XOR;
3305 break;
3306 }
3307
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003308 if (FinalDstReg == Mips::NoRegister)
3309 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3310 else
3311 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3312 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003313 return false;
3314 }
3315 return true;
3316}
3317
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003318bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
3319 SmallVectorImpl<MCInst> &Instructions) {
3320 unsigned ATReg = Mips::NoRegister;
3321 unsigned DReg = Inst.getOperand(0).getReg();
3322 unsigned SReg = Inst.getOperand(1).getReg();
3323 unsigned TReg = Inst.getOperand(2).getReg();
3324 unsigned TmpReg = DReg;
3325
3326 unsigned FirstShift = Mips::NOP;
3327 unsigned SecondShift = Mips::NOP;
3328
3329 if (hasMips32r2()) {
3330
3331 if (DReg == SReg) {
3332 TmpReg = getATReg(Inst.getLoc());
3333 if (!TmpReg)
3334 return true;
3335 }
3336
3337 if (Inst.getOpcode() == Mips::ROL) {
3338 emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3339 emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3340 return false;
3341 }
3342
3343 if (Inst.getOpcode() == Mips::ROR) {
3344 emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3345 return false;
3346 }
3347
3348 return true;
3349 }
3350
3351 if (hasMips32()) {
3352
3353 switch (Inst.getOpcode()) {
3354 default:
3355 llvm_unreachable("unexpected instruction opcode");
3356 case Mips::ROL:
3357 FirstShift = Mips::SRLV;
3358 SecondShift = Mips::SLLV;
3359 break;
3360 case Mips::ROR:
3361 FirstShift = Mips::SLLV;
3362 SecondShift = Mips::SRLV;
3363 break;
3364 }
3365
3366 ATReg = getATReg(Inst.getLoc());
3367 if (!ATReg)
3368 return true;
3369
3370 emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3371 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3372 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3373 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3374
3375 return false;
3376 }
3377
3378 return true;
3379}
3380
3381bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
3382 SmallVectorImpl<MCInst> &Instructions) {
3383
3384 unsigned ATReg = Mips::NoRegister;
3385 unsigned DReg = Inst.getOperand(0).getReg();
3386 unsigned SReg = Inst.getOperand(1).getReg();
3387 int64_t ImmValue = Inst.getOperand(2).getImm();
3388
3389 unsigned FirstShift = Mips::NOP;
3390 unsigned SecondShift = Mips::NOP;
3391
3392 if (hasMips32r2()) {
3393
3394 if (Inst.getOpcode() == Mips::ROLImm) {
3395 uint64_t MaxShift = 32;
3396 uint64_t ShiftValue = ImmValue;
3397 if (ImmValue != 0)
3398 ShiftValue = MaxShift - ImmValue;
3399 emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3400 return false;
3401 }
3402
3403 if (Inst.getOpcode() == Mips::RORImm) {
3404 emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3405 return false;
3406 }
3407
3408 return true;
3409 }
3410
3411 if (hasMips32()) {
3412
3413 if (ImmValue == 0) {
3414 emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3415 return false;
3416 }
3417
3418 switch (Inst.getOpcode()) {
3419 default:
3420 llvm_unreachable("unexpected instruction opcode");
3421 case Mips::ROLImm:
3422 FirstShift = Mips::SLL;
3423 SecondShift = Mips::SRL;
3424 break;
3425 case Mips::RORImm:
3426 FirstShift = Mips::SRL;
3427 SecondShift = Mips::SLL;
3428 break;
3429 }
3430
3431 ATReg = getATReg(Inst.getLoc());
3432 if (!ATReg)
3433 return true;
3434
3435 emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3436 emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions);
3437 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3438
3439 return false;
3440 }
3441
3442 return true;
3443}
3444
3445bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
3446 SmallVectorImpl<MCInst> &Instructions) {
3447
3448 unsigned ATReg = Mips::NoRegister;
3449 unsigned DReg = Inst.getOperand(0).getReg();
3450 unsigned SReg = Inst.getOperand(1).getReg();
3451 unsigned TReg = Inst.getOperand(2).getReg();
3452 unsigned TmpReg = DReg;
3453
3454 unsigned FirstShift = Mips::NOP;
3455 unsigned SecondShift = Mips::NOP;
3456
3457 if (hasMips64r2()) {
3458
3459 if (TmpReg == SReg) {
3460 TmpReg = getATReg(Inst.getLoc());
3461 if (!TmpReg)
3462 return true;
3463 }
3464
3465 if (Inst.getOpcode() == Mips::DROL) {
3466 emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3467 emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3468 return false;
3469 }
3470
3471 if (Inst.getOpcode() == Mips::DROR) {
3472 emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3473 return false;
3474 }
3475
3476 return true;
3477 }
3478
3479 if (hasMips64()) {
3480
3481 switch (Inst.getOpcode()) {
3482 default:
3483 llvm_unreachable("unexpected instruction opcode");
3484 case Mips::DROL:
3485 FirstShift = Mips::DSRLV;
3486 SecondShift = Mips::DSLLV;
3487 break;
3488 case Mips::DROR:
3489 FirstShift = Mips::DSLLV;
3490 SecondShift = Mips::DSRLV;
3491 break;
3492 }
3493
3494 ATReg = getATReg(Inst.getLoc());
3495 if (!ATReg)
3496 return true;
3497
3498 emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3499 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3500 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3501 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3502
3503 return false;
3504 }
3505
3506 return true;
3507}
3508
3509bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
3510 SmallVectorImpl<MCInst> &Instructions) {
3511
3512 unsigned ATReg = Mips::NoRegister;
3513 unsigned DReg = Inst.getOperand(0).getReg();
3514 unsigned SReg = Inst.getOperand(1).getReg();
3515 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3516
3517 unsigned FirstShift = Mips::NOP;
3518 unsigned SecondShift = Mips::NOP;
3519
3520 MCInst TmpInst;
3521
3522 if (hasMips64r2()) {
3523
3524 unsigned FinalOpcode = Mips::NOP;
3525 if (ImmValue == 0)
3526 FinalOpcode = Mips::DROTR;
3527 else if (ImmValue % 32 == 0)
3528 FinalOpcode = Mips::DROTR32;
3529 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3530 if (Inst.getOpcode() == Mips::DROLImm)
3531 FinalOpcode = Mips::DROTR32;
3532 else
3533 FinalOpcode = Mips::DROTR;
3534 } else if (ImmValue >= 33) {
3535 if (Inst.getOpcode() == Mips::DROLImm)
3536 FinalOpcode = Mips::DROTR;
3537 else
3538 FinalOpcode = Mips::DROTR32;
3539 }
3540
3541 uint64_t ShiftValue = ImmValue % 32;
3542 if (Inst.getOpcode() == Mips::DROLImm)
3543 ShiftValue = (32 - ImmValue % 32) % 32;
3544
3545 emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3546
3547 return false;
3548 }
3549
3550 if (hasMips64()) {
3551
3552 if (ImmValue == 0) {
3553 emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3554 return false;
3555 }
3556
3557 switch (Inst.getOpcode()) {
3558 default:
3559 llvm_unreachable("unexpected instruction opcode");
3560 case Mips::DROLImm:
3561 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3562 FirstShift = Mips::DSLL;
3563 SecondShift = Mips::DSRL32;
3564 }
3565 if (ImmValue == 32) {
3566 FirstShift = Mips::DSLL32;
3567 SecondShift = Mips::DSRL32;
3568 }
3569 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3570 FirstShift = Mips::DSLL32;
3571 SecondShift = Mips::DSRL;
3572 }
3573 break;
3574 case Mips::DRORImm:
3575 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3576 FirstShift = Mips::DSRL;
3577 SecondShift = Mips::DSLL32;
3578 }
3579 if (ImmValue == 32) {
3580 FirstShift = Mips::DSRL32;
3581 SecondShift = Mips::DSLL32;
3582 }
3583 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3584 FirstShift = Mips::DSRL32;
3585 SecondShift = Mips::DSLL;
3586 }
3587 break;
3588 }
3589
3590 ATReg = getATReg(Inst.getLoc());
3591 if (!ATReg)
3592 return true;
3593
3594 emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions);
3595 emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions);
3596 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3597
3598 return false;
3599 }
3600
3601 return true;
3602}
3603
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003604bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc,
3605 SmallVectorImpl<MCInst> &Instructions) {
3606
3607 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3608 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3609
3610 emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, Instructions);
3611 if (FirstRegOp != SecondRegOp)
3612 emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, Instructions);
3613 else
3614 createNop(false, IDLoc, Instructions);
3615 emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, Instructions);
3616
3617 return false;
3618}
3619
Toma Tabacu234482a2015-03-16 12:03:39 +00003620void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3621 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003622 if (hasShortDelaySlot)
3623 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3624 else
3625 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003626}
3627
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003628void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003629 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003630 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003631 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3632 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003633}
3634
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003635void MipsAsmParser::createCpRestoreMemOp(
3636 bool IsLoad, int StackOffset, SMLoc IDLoc,
3637 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003638 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003639 if (!isInt<16>(StackOffset)) {
3640 MCInst MemInst;
3641 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3642 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3643 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3644 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003645 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003646 return;
3647 }
3648
3649 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3650 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003651}
3652
Matheus Almeida595fcab2014-06-11 15:05:56 +00003653unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3654 // As described by the Mips32r2 spec, the registers Rd and Rs for
3655 // jalr.hb must be different.
3656 unsigned Opcode = Inst.getOpcode();
3657
3658 if (Opcode == Mips::JALR_HB &&
3659 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3660 return Match_RequiresDifferentSrcAndDst;
3661
3662 return Match_Success;
3663}
3664
Daniel Sanders52da7af2015-11-06 12:11:03 +00003665static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3666 uint64_t ErrorInfo) {
3667 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3668 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3669 if (ErrorLoc == SMLoc())
3670 return Loc;
3671 return ErrorLoc;
3672 }
3673 return Loc;
3674}
3675
David Blaikie960ea3f2014-06-08 16:18:35 +00003676bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3677 OperandVector &Operands,
3678 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003679 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003680 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003681
Jack Carterb4dbc172012-09-05 23:34:03 +00003682 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003683 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003684 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003685 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003686
3687 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003688 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003689 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003690 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003691 for (unsigned i = 0; i < Instructions.size(); i++)
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003692 Out.EmitInstruction(Instructions[i], getSTI());
Jack Carterb4dbc172012-09-05 23:34:03 +00003693 return false;
3694 }
3695 case Match_MissingFeature:
3696 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3697 return true;
3698 case Match_InvalidOperand: {
3699 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003700 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003701 if (ErrorInfo >= Operands.size())
3702 return Error(IDLoc, "too few operands for instruction");
3703
Daniel Sanders52da7af2015-11-06 12:11:03 +00003704 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003705 if (ErrorLoc == SMLoc())
3706 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003707 }
3708
3709 return Error(ErrorLoc, "invalid operand for instruction");
3710 }
3711 case Match_MnemonicFail:
3712 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003713 case Match_RequiresDifferentSrcAndDst:
3714 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003715 case Match_Immz:
3716 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003717 case Match_UImm1_0:
3718 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3719 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003720 case Match_UImm2_0:
3721 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3722 "expected 2-bit unsigned immediate");
3723 case Match_UImm2_1:
3724 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3725 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003726 case Match_UImm3_0:
3727 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3728 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003729 case Match_UImm4_0:
3730 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3731 "expected 4-bit unsigned immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003732 case Match_UImm5_0:
3733 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3734 "expected 5-bit unsigned immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003735 case Match_UImm5_1:
3736 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3737 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003738 case Match_UImm5_32:
3739 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3740 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003741 case Match_UImm5_33:
3742 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3743 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003744 case Match_UImm5_0_Report_UImm6:
3745 // This is used on UImm5 operands that have a corresponding UImm5_32
3746 // operand to avoid confusing the user.
3747 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3748 "expected 6-bit unsigned immediate");
3749 case Match_UImm5_Lsl2:
3750 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3751 "expected both 7-bit unsigned immediate and multiple of 4");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003752 case Match_UImm6_0:
3753 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3754 "expected 6-bit unsigned immediate");
Zlatko Buljan252cca52015-12-18 08:59:37 +00003755 case Match_SImm6:
3756 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3757 "expected 6-bit signed immediate");
3758 case Match_UImm7_0:
3759 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3760 "expected 7-bit unsigned immediate");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003761 case Match_UImm8_0:
3762 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3763 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003764 case Match_UImm10_0:
3765 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3766 "expected 10-bit unsigned immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003767 case Match_UImm16:
3768 case Match_UImm16_Relaxed:
3769 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3770 "expected 16-bit unsigned immediate");
Jack Carterb4dbc172012-09-05 23:34:03 +00003771 }
Craig Topper589ceee2015-01-03 08:16:34 +00003772
3773 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003774}
3775
Toma Tabacud9d344b2015-04-27 14:05:04 +00003776void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3777 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3778 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3779 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003780}
3781
Toma Tabacu81496c12015-05-20 08:54:45 +00003782void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3783 if (!AssemblerOptions.back()->isMacro())
3784 Warning(Loc, "macro instruction expanded into multiple instructions");
3785}
3786
Daniel Sandersef638fe2014-10-03 15:37:37 +00003787void
3788MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3789 SMRange Range, bool ShowColors) {
3790 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003791 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003792 ShowColors);
3793}
3794
Jack Carter1ac53222013-02-20 23:11:17 +00003795int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003796 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003797
Vladimir Medic4c299852013-11-06 11:27:05 +00003798 CC = StringSwitch<unsigned>(Name)
3799 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003800 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003801 .Case("a0", 4)
3802 .Case("a1", 5)
3803 .Case("a2", 6)
3804 .Case("a3", 7)
3805 .Case("v0", 2)
3806 .Case("v1", 3)
3807 .Case("s0", 16)
3808 .Case("s1", 17)
3809 .Case("s2", 18)
3810 .Case("s3", 19)
3811 .Case("s4", 20)
3812 .Case("s5", 21)
3813 .Case("s6", 22)
3814 .Case("s7", 23)
3815 .Case("k0", 26)
3816 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003817 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003818 .Case("sp", 29)
3819 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003820 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003821 .Case("ra", 31)
3822 .Case("t0", 8)
3823 .Case("t1", 9)
3824 .Case("t2", 10)
3825 .Case("t3", 11)
3826 .Case("t4", 12)
3827 .Case("t5", 13)
3828 .Case("t6", 14)
3829 .Case("t7", 15)
3830 .Case("t8", 24)
3831 .Case("t9", 25)
3832 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003833
Toma Tabacufda445c2014-09-15 15:33:01 +00003834 if (!(isABI_N32() || isABI_N64()))
3835 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003836
Daniel Sandersef638fe2014-10-03 15:37:37 +00003837 if (12 <= CC && CC <= 15) {
3838 // Name is one of t4-t7
3839 AsmToken RegTok = getLexer().peekTok();
3840 SMRange RegRange = RegTok.getLocRange();
3841
3842 StringRef FixedName = StringSwitch<StringRef>(Name)
3843 .Case("t4", "t0")
3844 .Case("t5", "t1")
3845 .Case("t6", "t2")
3846 .Case("t7", "t3")
3847 .Default("");
3848 assert(FixedName != "" && "Register name is not one of t4-t7.");
3849
3850 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3851 "Did you mean $" + FixedName + "?", RegRange);
3852 }
3853
Toma Tabacufda445c2014-09-15 15:33:01 +00003854 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3855 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3856 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3857 if (8 <= CC && CC <= 11)
3858 CC += 4;
3859
3860 if (CC == -1)
3861 CC = StringSwitch<unsigned>(Name)
3862 .Case("a4", 8)
3863 .Case("a5", 9)
3864 .Case("a6", 10)
3865 .Case("a7", 11)
3866 .Case("kt0", 26)
3867 .Case("kt1", 27)
3868 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003869
3870 return CC;
3871}
Jack Carterd0bd6422013-04-18 00:41:53 +00003872
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003873int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3874 int CC;
3875
3876 CC = StringSwitch<unsigned>(Name)
3877 .Case("hwr_cpunum", 0)
3878 .Case("hwr_synci_step", 1)
3879 .Case("hwr_cc", 2)
3880 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003881 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003882 .Default(-1);
3883
3884 return CC;
3885}
3886
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003887int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003888
Jack Cartera63b16a2012-09-07 00:23:42 +00003889 if (Name[0] == 'f') {
3890 StringRef NumString = Name.substr(1);
3891 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003892 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003893 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003894 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003895 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003896 return IntVal;
3897 }
3898 return -1;
3899}
Jack Cartera63b16a2012-09-07 00:23:42 +00003900
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003901int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3902
3903 if (Name.startswith("fcc")) {
3904 StringRef NumString = Name.substr(3);
3905 unsigned IntVal;
3906 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003907 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003908 if (IntVal > 7) // There are only 8 fcc registers.
3909 return -1;
3910 return IntVal;
3911 }
3912 return -1;
3913}
3914
3915int MipsAsmParser::matchACRegisterName(StringRef Name) {
3916
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003917 if (Name.startswith("ac")) {
3918 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003919 unsigned IntVal;
3920 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003921 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003922 if (IntVal > 3) // There are only 3 acc registers.
3923 return -1;
3924 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003925 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003926 return -1;
3927}
Jack Carterd0bd6422013-04-18 00:41:53 +00003928
Jack Carter5dc8ac92013-09-25 23:50:44 +00003929int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3930 unsigned IntVal;
3931
3932 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3933 return -1;
3934
3935 if (IntVal > 31)
3936 return -1;
3937
3938 return IntVal;
3939}
3940
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003941int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3942 int CC;
3943
3944 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003945 .Case("msair", 0)
3946 .Case("msacsr", 1)
3947 .Case("msaaccess", 2)
3948 .Case("msasave", 3)
3949 .Case("msamodify", 4)
3950 .Case("msarequest", 5)
3951 .Case("msamap", 6)
3952 .Case("msaunmap", 7)
3953 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003954
3955 return CC;
3956}
3957
Toma Tabacu89a712b2015-04-15 10:48:56 +00003958unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003959 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003960 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003961 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003962 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003963 return 0;
3964 }
3965 unsigned AT = getReg(
3966 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003967 return AT;
3968}
Jack Carter0b744b32012-10-04 02:29:46 +00003969
Jack Carterd0bd6422013-04-18 00:41:53 +00003970unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003971 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003972}
3973
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003974unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003975 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003976 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003977}
3978
Jack Carter873c7242013-01-12 01:03:14 +00003979int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003980 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003981 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003982 return -1;
3983
Jack Carter873c7242013-01-12 01:03:14 +00003984 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003985}
3986
Toma Tabacu13964452014-09-04 13:23:44 +00003987bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003988 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003989 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003990
Jack Carter30a59822012-10-04 04:03:53 +00003991 // Check if the current operand has a custom associated parser, if so, try to
3992 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003993 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3994 if (ResTy == MatchOperand_Success)
3995 return false;
3996 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3997 // there was a match, but an error occurred, in which case, just return that
3998 // the operand parsing failed.
3999 if (ResTy == MatchOperand_ParseFail)
4000 return true;
4001
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004002 DEBUG(dbgs() << ".. Generic Parser\n");
4003
Jack Carterb4dbc172012-09-05 23:34:03 +00004004 switch (getLexer().getKind()) {
4005 default:
4006 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4007 return true;
4008 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004009 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004010 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004011
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004012 // Almost all registers have been parsed by custom parsers. There is only
4013 // one exception to this. $zero (and it's alias $0) will reach this point
4014 // for div, divu, and similar instructions because it is not an operand
4015 // to the instruction definition but an explicit register. Special case
4016 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004017 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004018 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004019
Jack Carterd0bd6422013-04-18 00:41:53 +00004020 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004021 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004022 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004023 return true;
4024
Jack Carter873c7242013-01-12 01:03:14 +00004025 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004026 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004027 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004028 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004029 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004030
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004031 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004032 return false;
4033 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004034 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004035 case AsmToken::LParen:
4036 case AsmToken::Minus:
4037 case AsmToken::Plus:
4038 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004039 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004040 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004041 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004042 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004043 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004044 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004045 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004046 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004047 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004048 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004049 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004050 return true;
4051
Jack Carter873c7242013-01-12 01:03:14 +00004052 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4053
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004054 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004055 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004056 } // case AsmToken::Percent
4057 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004058 return true;
4059}
4060
Vladimir Medic4c299852013-11-06 11:27:05 +00004061const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004062 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004063 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00004064 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004065 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00004066 // It's a constant, evaluate reloc value.
4067 int16_t Val;
4068 switch (getVariantKind(RelocStr)) {
4069 case MCSymbolRefExpr::VK_Mips_ABS_LO:
4070 // Get the 1st 16-bits.
4071 Val = MCE->getValue() & 0xffff;
4072 break;
4073 case MCSymbolRefExpr::VK_Mips_ABS_HI:
Simon Atanasyan2fc1e3b2016-02-09 22:31:49 +00004074 case MCSymbolRefExpr::VK_Mips_GOT:
Sasa Stankovic06c47802014-04-03 10:37:45 +00004075 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
4076 // 16 bits being negative.
4077 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
4078 break;
4079 case MCSymbolRefExpr::VK_Mips_HIGHER:
4080 // Get the 3rd 16-bits.
4081 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
4082 break;
4083 case MCSymbolRefExpr::VK_Mips_HIGHEST:
4084 // Get the 4th 16-bits.
4085 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
4086 break;
4087 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00004088 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00004089 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004090 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004091 }
4092
Jack Carterb5cf5902013-04-17 00:18:04 +00004093 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004094 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00004095 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00004096 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004097 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004098 return Res;
4099 }
4100
4101 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00004102 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
4103
Sasa Stankovic06c47802014-04-03 10:37:45 +00004104 // Try to create target expression.
4105 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00004106 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004107
Jack Carterd0bd6422013-04-18 00:41:53 +00004108 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
4109 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004110 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004111 return Res;
4112 }
4113
4114 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004115 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004116 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00004117 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00004118 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004119 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004120 return Expr;
4121}
4122
4123bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4124
4125 switch (Expr->getKind()) {
4126 case MCExpr::Constant:
4127 return true;
4128 case MCExpr::SymbolRef:
4129 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4130 case MCExpr::Binary:
4131 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4132 if (!isEvaluated(BE->getLHS()))
4133 return false;
4134 return isEvaluated(BE->getRHS());
4135 }
4136 case MCExpr::Unary:
4137 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004138 case MCExpr::Target:
4139 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004140 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004141 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004142}
Jack Carterd0bd6422013-04-18 00:41:53 +00004143
Jack Carterb5cf5902013-04-17 00:18:04 +00004144bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004145 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004146 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004147 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004148 if (Tok.isNot(AsmToken::Identifier))
4149 return true;
4150
Yaron Keren075759a2015-03-30 15:42:36 +00004151 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004152
Jack Carterd0bd6422013-04-18 00:41:53 +00004153 Parser.Lex(); // Eat the identifier.
4154 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004155 const MCExpr *IdVal;
4156 SMLoc EndLoc;
4157
4158 if (getLexer().getKind() == AsmToken::LParen) {
4159 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004160 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004161 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004162 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004163 const AsmToken &nextTok = Parser.getTok();
4164 if (nextTok.isNot(AsmToken::Identifier))
4165 return true;
4166 Str += "(%";
4167 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004168 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004169 if (getLexer().getKind() != AsmToken::LParen)
4170 return true;
4171 } else
4172 break;
4173 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004174 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004175 return true;
4176
4177 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004178 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004179
4180 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004181 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004182
Jack Carterd0bd6422013-04-18 00:41:53 +00004183 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004184 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004185}
4186
Jack Carterb4dbc172012-09-05 23:34:03 +00004187bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4188 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004189 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004190 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004191 if (ResTy == MatchOperand_Success) {
4192 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004193 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004194 StartLoc = Operand.getStartLoc();
4195 EndLoc = Operand.getEndLoc();
4196
4197 // AFAIK, we only support numeric registers and named GPR's in CFI
4198 // directives.
4199 // Don't worry about eating tokens before failing. Using an unrecognised
4200 // register is a parse error.
4201 if (Operand.isGPRAsmReg()) {
4202 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004203 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004204 }
4205
4206 return (RegNo == (unsigned)-1);
4207 }
4208
4209 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004210 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004211}
4212
Jack Carterb5cf5902013-04-17 00:18:04 +00004213bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004214 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004215 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004216 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004217 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004218
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004219 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004220 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004221 ++NumOfLParen;
4222 }
Jack Carter873c7242013-01-12 01:03:14 +00004223
Jack Carterd0bd6422013-04-18 00:41:53 +00004224 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004225 default:
4226 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004227 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004228 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004229 case AsmToken::Integer:
4230 case AsmToken::Minus:
4231 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004232 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004233 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004234 else
4235 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004236 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004237 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004238 break;
Jack Carter873c7242013-01-12 01:03:14 +00004239 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004240 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004241 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004242 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004243}
4244
David Blaikie960ea3f2014-06-08 16:18:35 +00004245MipsAsmParser::OperandMatchResultTy
4246MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004247 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004248 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004249 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004250 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004251 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004252 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004253 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004254 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004255
Jack Carterb5cf5902013-04-17 00:18:04 +00004256 if (getLexer().getKind() == AsmToken::LParen) {
4257 Parser.Lex();
4258 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004259 }
4260
Jack Carterb5cf5902013-04-17 00:18:04 +00004261 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004262 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004263 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004264
Jack Carterd0bd6422013-04-18 00:41:53 +00004265 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004266 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004267 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004268 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004269 SMLoc E =
4270 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004271 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004272 return MatchOperand_Success;
4273 }
4274 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004275 SMLoc E =
4276 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004277
Jack Carterd0bd6422013-04-18 00:41:53 +00004278 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004279 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004280 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004281 S, E, *this);
4282 Operands.push_back(
4283 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004284 return MatchOperand_Success;
4285 }
4286 Error(Parser.getTok().getLoc(), "'(' expected");
4287 return MatchOperand_ParseFail;
4288 }
4289
Jack Carterd0bd6422013-04-18 00:41:53 +00004290 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004291 }
4292
Toma Tabacu13964452014-09-04 13:23:44 +00004293 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004294 if (Res != MatchOperand_Success)
4295 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004296
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004297 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004298 Error(Parser.getTok().getLoc(), "')' expected");
4299 return MatchOperand_ParseFail;
4300 }
4301
Jack Carter873c7242013-01-12 01:03:14 +00004302 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4303
Jack Carterd0bd6422013-04-18 00:41:53 +00004304 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004305
Craig Topper062a2ba2014-04-25 05:30:21 +00004306 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004307 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004308
Jack Carterd0bd6422013-04-18 00:41:53 +00004309 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004310 std::unique_ptr<MipsOperand> op(
4311 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004312 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004313 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004314 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004315 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004316 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4317 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004318 if (IdVal->evaluateAsAbsolute(Imm))
4319 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004320 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004321 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004322 getContext());
4323 }
4324
David Blaikie960ea3f2014-06-08 16:18:35 +00004325 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004326 return MatchOperand_Success;
4327}
4328
David Blaikie960ea3f2014-06-08 16:18:35 +00004329bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004330 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004331 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004332 if (Sym) {
4333 SMLoc S = Parser.getTok().getLoc();
4334 const MCExpr *Expr;
4335 if (Sym->isVariable())
4336 Expr = Sym->getVariableValue();
4337 else
4338 return false;
4339 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004340 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004341 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004342 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004343 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004344 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004345 if (ResTy == MatchOperand_Success) {
4346 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004347 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004348 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004349 llvm_unreachable("Should never ParseFail");
4350 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004351 }
4352 } else if (Expr->getKind() == MCExpr::Constant) {
4353 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004354 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004355 Operands.push_back(
4356 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004357 return true;
4358 }
4359 }
4360 return false;
4361}
Jack Carterd0bd6422013-04-18 00:41:53 +00004362
Jack Carter873c7242013-01-12 01:03:14 +00004363MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004364MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004365 StringRef Identifier,
4366 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004367 int Index = matchCPURegisterName(Identifier);
4368 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004369 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004370 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4371 return MatchOperand_Success;
4372 }
4373
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004374 Index = matchHWRegsRegisterName(Identifier);
4375 if (Index != -1) {
4376 Operands.push_back(MipsOperand::createHWRegsReg(
4377 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4378 return MatchOperand_Success;
4379 }
4380
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004381 Index = matchFPURegisterName(Identifier);
4382 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004383 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004384 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4385 return MatchOperand_Success;
4386 }
4387
4388 Index = matchFCCRegisterName(Identifier);
4389 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004390 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004391 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4392 return MatchOperand_Success;
4393 }
4394
4395 Index = matchACRegisterName(Identifier);
4396 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004397 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004398 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4399 return MatchOperand_Success;
4400 }
4401
4402 Index = matchMSA128RegisterName(Identifier);
4403 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004404 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004405 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4406 return MatchOperand_Success;
4407 }
4408
4409 Index = matchMSA128CtrlRegisterName(Identifier);
4410 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004411 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004412 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4413 return MatchOperand_Success;
4414 }
4415
4416 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004417}
4418
4419MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004420MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004421 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004422 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004423
4424 if (Token.is(AsmToken::Identifier)) {
4425 DEBUG(dbgs() << ".. identifier\n");
4426 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004427 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004428 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004429 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004430 } else if (Token.is(AsmToken::Integer)) {
4431 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004432 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004433 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4434 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004435 return MatchOperand_Success;
4436 }
4437
4438 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4439
4440 return MatchOperand_NoMatch;
4441}
4442
David Blaikie960ea3f2014-06-08 16:18:35 +00004443MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004444MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004445 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004446 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004447
4448 auto Token = Parser.getTok();
4449
4450 SMLoc S = Token.getLoc();
4451
4452 if (Token.isNot(AsmToken::Dollar)) {
4453 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4454 if (Token.is(AsmToken::Identifier)) {
4455 if (searchSymbolAlias(Operands))
4456 return MatchOperand_Success;
4457 }
4458 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4459 return MatchOperand_NoMatch;
4460 }
4461 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004462
Toma Tabacu13964452014-09-04 13:23:44 +00004463 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004464 if (ResTy == MatchOperand_Success) {
4465 Parser.Lex(); // $
4466 Parser.Lex(); // identifier
4467 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004468 return ResTy;
4469}
4470
4471MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004472MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004473 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004474 switch (getLexer().getKind()) {
4475 default:
4476 return MatchOperand_NoMatch;
4477 case AsmToken::LParen:
4478 case AsmToken::Minus:
4479 case AsmToken::Plus:
4480 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004481 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004482 case AsmToken::String:
4483 break;
4484 }
4485
4486 const MCExpr *IdVal;
4487 SMLoc S = Parser.getTok().getLoc();
4488 if (getParser().parseExpression(IdVal))
4489 return MatchOperand_ParseFail;
4490
4491 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4492 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4493 return MatchOperand_Success;
4494}
4495
David Blaikie960ea3f2014-06-08 16:18:35 +00004496MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004497MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004498 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004499 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004500
4501 SMLoc S = getLexer().getLoc();
4502
4503 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004504 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004505 if (ResTy != MatchOperand_NoMatch)
4506 return ResTy;
4507
Daniel Sanders315386c2014-04-01 10:40:14 +00004508 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004509 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004510 if (ResTy != MatchOperand_NoMatch)
4511 return ResTy;
4512
Daniel Sandersffd84362014-04-01 10:41:48 +00004513 const MCExpr *Expr = nullptr;
4514 if (Parser.parseExpression(Expr)) {
4515 // We have no way of knowing if a symbol was consumed so we must ParseFail
4516 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004517 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004518 Operands.push_back(
4519 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004520 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004521}
4522
Vladimir Medic2b953d02013-10-01 09:48:56 +00004523MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004524MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004525 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004526 const MCExpr *IdVal;
4527 // If the first token is '$' we may have register operand.
4528 if (Parser.getTok().is(AsmToken::Dollar))
4529 return MatchOperand_NoMatch;
4530 SMLoc S = Parser.getTok().getLoc();
4531 if (getParser().parseExpression(IdVal))
4532 return MatchOperand_ParseFail;
4533 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004534 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004535 int64_t Val = MCE->getValue();
4536 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4537 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004538 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004539 return MatchOperand_Success;
4540}
4541
Matheus Almeida779c5932013-11-18 12:32:49 +00004542MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004543MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004544 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004545 switch (getLexer().getKind()) {
4546 default:
4547 return MatchOperand_NoMatch;
4548 case AsmToken::LParen:
4549 case AsmToken::Plus:
4550 case AsmToken::Minus:
4551 case AsmToken::Integer:
4552 break;
4553 }
4554
4555 const MCExpr *Expr;
4556 SMLoc S = Parser.getTok().getLoc();
4557
4558 if (getParser().parseExpression(Expr))
4559 return MatchOperand_ParseFail;
4560
4561 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004562 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004563 Error(S, "expected immediate value");
4564 return MatchOperand_ParseFail;
4565 }
4566
4567 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4568 // and because the CPU always adds one to the immediate field, the allowed
4569 // range becomes 1..4. We'll only check the range here and will deal
4570 // with the addition/subtraction when actually decoding/encoding
4571 // the instruction.
4572 if (Val < 1 || Val > 4) {
4573 Error(S, "immediate not in range (1..4)");
4574 return MatchOperand_ParseFail;
4575 }
4576
Jack Carter3b2c96e2014-01-22 23:31:38 +00004577 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004578 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004579 return MatchOperand_Success;
4580}
4581
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004582MipsAsmParser::OperandMatchResultTy
4583MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4584 MCAsmParser &Parser = getParser();
4585 SmallVector<unsigned, 10> Regs;
4586 unsigned RegNo;
4587 unsigned PrevReg = Mips::NoRegister;
4588 bool RegRange = false;
4589 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4590
4591 if (Parser.getTok().isNot(AsmToken::Dollar))
4592 return MatchOperand_ParseFail;
4593
4594 SMLoc S = Parser.getTok().getLoc();
4595 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4596 SMLoc E = getLexer().getLoc();
4597 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4598 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4599 if (RegRange) {
4600 // Remove last register operand because registers from register range
4601 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004602 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4603 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004604 Regs.push_back(RegNo);
4605 } else {
4606 unsigned TmpReg = PrevReg + 1;
4607 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004608 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4609 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4610 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004611 Error(E, "invalid register operand");
4612 return MatchOperand_ParseFail;
4613 }
4614
4615 PrevReg = TmpReg;
4616 Regs.push_back(TmpReg++);
4617 }
4618 }
4619
4620 RegRange = false;
4621 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004622 if ((PrevReg == Mips::NoRegister) &&
4623 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4624 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004625 Error(E, "$16 or $31 expected");
4626 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004627 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4628 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4629 !isGP64bit()) ||
4630 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4631 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4632 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004633 Error(E, "invalid register operand");
4634 return MatchOperand_ParseFail;
4635 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004636 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4637 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4638 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004639 Error(E, "consecutive register numbers expected");
4640 return MatchOperand_ParseFail;
4641 }
4642
4643 Regs.push_back(RegNo);
4644 }
4645
4646 if (Parser.getTok().is(AsmToken::Minus))
4647 RegRange = true;
4648
4649 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4650 !Parser.getTok().isNot(AsmToken::Comma)) {
4651 Error(E, "',' or '-' expected");
4652 return MatchOperand_ParseFail;
4653 }
4654
4655 Lex(); // Consume comma or minus
4656 if (Parser.getTok().isNot(AsmToken::Dollar))
4657 break;
4658
4659 PrevReg = RegNo;
4660 }
4661
4662 SMLoc E = Parser.getTok().getLoc();
4663 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4664 parseMemOperand(Operands);
4665 return MatchOperand_Success;
4666}
4667
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004668MipsAsmParser::OperandMatchResultTy
4669MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4670 MCAsmParser &Parser = getParser();
4671
4672 SMLoc S = Parser.getTok().getLoc();
4673 if (parseAnyRegister(Operands) != MatchOperand_Success)
4674 return MatchOperand_ParseFail;
4675
4676 SMLoc E = Parser.getTok().getLoc();
4677 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4678 unsigned Reg = Op.getGPR32Reg();
4679 Operands.pop_back();
4680 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4681 return MatchOperand_Success;
4682}
4683
Zoran Jovanovic41688672015-02-10 16:36:20 +00004684MipsAsmParser::OperandMatchResultTy
4685MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4686 MCAsmParser &Parser = getParser();
4687 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4688 SmallVector<unsigned, 10> Regs;
4689
4690 if (Parser.getTok().isNot(AsmToken::Dollar))
4691 return MatchOperand_ParseFail;
4692
4693 SMLoc S = Parser.getTok().getLoc();
4694
4695 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4696 return MatchOperand_ParseFail;
4697
4698 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4699 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4700 Regs.push_back(RegNo);
4701
4702 SMLoc E = Parser.getTok().getLoc();
4703 if (Parser.getTok().isNot(AsmToken::Comma)) {
4704 Error(E, "',' expected");
4705 return MatchOperand_ParseFail;
4706 }
4707
4708 // Remove comma.
4709 Parser.Lex();
4710
4711 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4712 return MatchOperand_ParseFail;
4713
4714 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4715 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4716 Regs.push_back(RegNo);
4717
4718 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4719
4720 return MatchOperand_Success;
4721}
4722
Jack Carterdc1e35d2012-09-06 20:00:02 +00004723MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4724
Vladimir Medic4c299852013-11-06 11:27:05 +00004725 MCSymbolRefExpr::VariantKind VK =
4726 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4727 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4728 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4729 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4730 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4731 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4732 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4733 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4734 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4735 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4736 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4737 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4738 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4739 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4740 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4741 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4742 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4743 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004744 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4745 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4746 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4747 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4748 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4749 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004750 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4751 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004752 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004753
Matheus Almeida2852af82014-04-22 10:15:54 +00004754 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004755
Jack Carterdc1e35d2012-09-06 20:00:02 +00004756 return VK;
4757}
Jack Cartera63b16a2012-09-07 00:23:42 +00004758
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004759/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4760/// either this.
4761/// ::= '(', register, ')'
4762/// handle it before we iterate so we don't get tripped up by the lack of
4763/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004764bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004765 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004766 if (getLexer().is(AsmToken::LParen)) {
4767 Operands.push_back(
4768 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4769 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004770 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004771 SMLoc Loc = getLexer().getLoc();
4772 Parser.eatToEndOfStatement();
4773 return Error(Loc, "unexpected token in argument list");
4774 }
4775 if (Parser.getTok().isNot(AsmToken::RParen)) {
4776 SMLoc Loc = getLexer().getLoc();
4777 Parser.eatToEndOfStatement();
4778 return Error(Loc, "unexpected token, expected ')'");
4779 }
4780 Operands.push_back(
4781 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4782 Parser.Lex();
4783 }
4784 return false;
4785}
4786
4787/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4788/// either one of these.
4789/// ::= '[', register, ']'
4790/// ::= '[', integer, ']'
4791/// handle it before we iterate so we don't get tripped up by the lack of
4792/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004793bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004794 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004795 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004796 if (getLexer().is(AsmToken::LBrac)) {
4797 Operands.push_back(
4798 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4799 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004800 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004801 SMLoc Loc = getLexer().getLoc();
4802 Parser.eatToEndOfStatement();
4803 return Error(Loc, "unexpected token in argument list");
4804 }
4805 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4806 SMLoc Loc = getLexer().getLoc();
4807 Parser.eatToEndOfStatement();
4808 return Error(Loc, "unexpected token, expected ']'");
4809 }
4810 Operands.push_back(
4811 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4812 Parser.Lex();
4813 }
4814 return false;
4815}
4816
David Blaikie960ea3f2014-06-08 16:18:35 +00004817bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4818 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004819 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004820 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004821
4822 // We have reached first instruction, module directive are now forbidden.
4823 getTargetStreamer().forbidModuleDirective();
4824
Vladimir Medic74593e62013-07-17 15:00:42 +00004825 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004826 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004827 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004828 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004829 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004830 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004831 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004832
4833 // Read the remaining operands.
4834 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4835 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004836 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004837 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004838 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004839 return Error(Loc, "unexpected token in argument list");
4840 }
Toma Tabacu13964452014-09-04 13:23:44 +00004841 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004842 return true;
4843 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004844
Jack Carterd0bd6422013-04-18 00:41:53 +00004845 while (getLexer().is(AsmToken::Comma)) {
4846 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004847 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004848 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004849 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004850 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004851 return Error(Loc, "unexpected token in argument list");
4852 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004853 // Parse bracket and parenthesis suffixes before we iterate
4854 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004855 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004856 return true;
4857 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004858 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004859 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004860 }
4861 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004862 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4863 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004864 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004865 return Error(Loc, "unexpected token in argument list");
4866 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004867 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004868 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004869}
4870
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004871bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004872 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004873 SMLoc Loc = getLexer().getLoc();
4874 Parser.eatToEndOfStatement();
4875 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004876}
4877
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004878bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004879 return Error(Loc, ErrorMsg);
4880}
4881
Jack Carter0b744b32012-10-04 02:29:46 +00004882bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004883 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004884 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004885
4886 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004887 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004888
4889 Parser.Lex(); // Eat "noat".
4890
Jack Carterd0bd6422013-04-18 00:41:53 +00004891 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004892 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004893 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004894 return false;
4895 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004896
4897 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004898 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004899 return false;
4900}
Jack Carterd0bd6422013-04-18 00:41:53 +00004901
Jack Carter0b744b32012-10-04 02:29:46 +00004902bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004903 // Line can be: ".set at", which sets $at to $1
4904 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004905 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004906 Parser.Lex(); // Eat "at".
4907
Jack Carter0b744b32012-10-04 02:29:46 +00004908 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004909 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004910 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004911
4912 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004913 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004914 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004915 }
4916
4917 if (getLexer().isNot(AsmToken::Equal)) {
4918 reportParseError("unexpected token, expected equals sign");
4919 return false;
4920 }
4921 Parser.Lex(); // Eat "=".
4922
4923 if (getLexer().isNot(AsmToken::Dollar)) {
4924 if (getLexer().is(AsmToken::EndOfStatement)) {
4925 reportParseError("no register specified");
4926 return false;
4927 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004928 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004929 return false;
4930 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004931 }
4932 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004933
Toma Tabacu16a74492015-02-13 10:30:57 +00004934 // Find out what "reg" is.
4935 unsigned AtRegNo;
4936 const AsmToken &Reg = Parser.getTok();
4937 if (Reg.is(AsmToken::Identifier)) {
4938 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4939 } else if (Reg.is(AsmToken::Integer)) {
4940 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004941 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004942 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004943 return false;
4944 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004945
4946 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004947 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004948 reportParseError("invalid register");
4949 return false;
4950 }
4951 Parser.Lex(); // Eat "reg".
4952
4953 // If this is not the end of the statement, report an error.
4954 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4955 reportParseError("unexpected token, expected end of statement");
4956 return false;
4957 }
4958
4959 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4960
4961 Parser.Lex(); // Consume the EndOfStatement.
4962 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004963}
4964
4965bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004966 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004967 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004968 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004969 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004970 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004971 return false;
4972 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004973 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004974 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004975 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004976 return false;
4977}
4978
4979bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004980 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004981 Parser.Lex();
4982 // If this is not the end of the statement, report an error.
4983 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004984 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004985 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004986 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004987 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004988 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004989 Parser.Lex(); // Consume the EndOfStatement.
4990 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004991}
4992
4993bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004994 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004995 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004996 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004997 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004998 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004999 return false;
5000 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005001 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005002 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005003 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005004 return false;
5005}
5006
5007bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005008 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005009 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005010 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005011 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005012 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005013 return false;
5014 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005015 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005016 reportParseError("`noreorder' must be set before `nomacro'");
5017 return false;
5018 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005019 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005020 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005021 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005022 return false;
5023}
Jack Carterd76b2372013-03-21 21:44:16 +00005024
Daniel Sanders44934432014-08-07 12:03:36 +00005025bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005026 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005027 Parser.Lex();
5028
5029 // If this is not the end of the statement, report an error.
5030 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005031 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005032
5033 setFeatureBits(Mips::FeatureMSA, "msa");
5034 getTargetStreamer().emitDirectiveSetMsa();
5035 return false;
5036}
5037
5038bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005039 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005040 Parser.Lex();
5041
5042 // If this is not the end of the statement, report an error.
5043 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005044 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005045
5046 clearFeatureBits(Mips::FeatureMSA, "msa");
5047 getTargetStreamer().emitDirectiveSetNoMsa();
5048 return false;
5049}
5050
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005051bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005052 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005053 Parser.Lex(); // Eat "nodsp".
5054
5055 // If this is not the end of the statement, report an error.
5056 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5057 reportParseError("unexpected token, expected end of statement");
5058 return false;
5059 }
5060
5061 clearFeatureBits(Mips::FeatureDSP, "dsp");
5062 getTargetStreamer().emitDirectiveSetNoDsp();
5063 return false;
5064}
5065
Toma Tabacucc2502d2014-11-04 17:18:07 +00005066bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005067 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005068 Parser.Lex(); // Eat "mips16".
5069
Jack Carter39536722014-01-22 23:08:42 +00005070 // If this is not the end of the statement, report an error.
5071 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005072 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005073 return false;
5074 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005075
5076 setFeatureBits(Mips::FeatureMips16, "mips16");
5077 getTargetStreamer().emitDirectiveSetMips16();
5078 Parser.Lex(); // Consume the EndOfStatement.
5079 return false;
5080}
5081
5082bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005083 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005084 Parser.Lex(); // Eat "nomips16".
5085
5086 // If this is not the end of the statement, report an error.
5087 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5088 reportParseError("unexpected token, expected end of statement");
5089 return false;
5090 }
5091
5092 clearFeatureBits(Mips::FeatureMips16, "mips16");
5093 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005094 Parser.Lex(); // Consume the EndOfStatement.
5095 return false;
5096}
5097
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005098bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005099 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005100 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005101 // Line can be: .set fp=32
5102 // .set fp=xx
5103 // .set fp=64
5104 Parser.Lex(); // Eat fp token
5105 AsmToken Tok = Parser.getTok();
5106 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005107 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005108 return false;
5109 }
5110 Parser.Lex(); // Eat '=' token.
5111 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005112
5113 if (!parseFpABIValue(FpAbiVal, ".set"))
5114 return false;
5115
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005116 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005117 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005118 return false;
5119 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005120 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005121 Parser.Lex(); // Consume the EndOfStatement.
5122 return false;
5123}
5124
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005125bool MipsAsmParser::parseSetOddSPRegDirective() {
5126 MCAsmParser &Parser = getParser();
5127
5128 Parser.Lex(); // Eat "oddspreg".
5129 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5130 reportParseError("unexpected token, expected end of statement");
5131 return false;
5132 }
5133
5134 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5135 getTargetStreamer().emitDirectiveSetOddSPReg();
5136 return false;
5137}
5138
5139bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5140 MCAsmParser &Parser = getParser();
5141
5142 Parser.Lex(); // Eat "nooddspreg".
5143 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5144 reportParseError("unexpected token, expected end of statement");
5145 return false;
5146 }
5147
5148 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5149 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5150 return false;
5151}
5152
Toma Tabacu9db22db2014-09-09 10:15:38 +00005153bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005154 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005155 SMLoc Loc = getLexer().getLoc();
5156
5157 Parser.Lex();
5158 if (getLexer().isNot(AsmToken::EndOfStatement))
5159 return reportParseError("unexpected token, expected end of statement");
5160
5161 // Always keep an element on the options "stack" to prevent the user
5162 // from changing the initial options. This is how we remember them.
5163 if (AssemblerOptions.size() == 2)
5164 return reportParseError(Loc, ".set pop with no .set push");
5165
Akira Hatanakab11ef082015-11-14 06:35:56 +00005166 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005167 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005168 setAvailableFeatures(
5169 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5170 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005171
5172 getTargetStreamer().emitDirectiveSetPop();
5173 return false;
5174}
5175
5176bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005177 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005178 Parser.Lex();
5179 if (getLexer().isNot(AsmToken::EndOfStatement))
5180 return reportParseError("unexpected token, expected end of statement");
5181
5182 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005183 AssemblerOptions.push_back(
5184 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005185
5186 getTargetStreamer().emitDirectiveSetPush();
5187 return false;
5188}
5189
Toma Tabacu29696502015-06-02 09:48:04 +00005190bool MipsAsmParser::parseSetSoftFloatDirective() {
5191 MCAsmParser &Parser = getParser();
5192 Parser.Lex();
5193 if (getLexer().isNot(AsmToken::EndOfStatement))
5194 return reportParseError("unexpected token, expected end of statement");
5195
5196 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5197 getTargetStreamer().emitDirectiveSetSoftFloat();
5198 return false;
5199}
5200
5201bool MipsAsmParser::parseSetHardFloatDirective() {
5202 MCAsmParser &Parser = getParser();
5203 Parser.Lex();
5204 if (getLexer().isNot(AsmToken::EndOfStatement))
5205 return reportParseError("unexpected token, expected end of statement");
5206
5207 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5208 getTargetStreamer().emitDirectiveSetHardFloat();
5209 return false;
5210}
5211
Jack Carterd76b2372013-03-21 21:44:16 +00005212bool MipsAsmParser::parseSetAssignment() {
5213 StringRef Name;
5214 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005215 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005216
5217 if (Parser.parseIdentifier(Name))
5218 reportParseError("expected identifier after .set");
5219
5220 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005221 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005222 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005223
Jack Carter3b2c96e2014-01-22 23:31:38 +00005224 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005225 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005226
Jim Grosbach6f482002015-05-18 18:43:14 +00005227 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005228 Sym->setVariableValue(Value);
5229
5230 return false;
5231}
Jack Carterd0bd6422013-04-18 00:41:53 +00005232
Toma Tabacu26647792014-09-09 12:52:14 +00005233bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005234 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005235 Parser.Lex();
5236 if (getLexer().isNot(AsmToken::EndOfStatement))
5237 return reportParseError("unexpected token, expected end of statement");
5238
5239 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005240 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005241 setAvailableFeatures(
5242 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5243 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005244 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5245
5246 getTargetStreamer().emitDirectiveSetMips0();
5247 return false;
5248}
5249
Toma Tabacu85618b32014-08-19 14:22:52 +00005250bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005251 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005252 Parser.Lex();
5253 if (getLexer().isNot(AsmToken::Equal))
5254 return reportParseError("unexpected token, expected equals sign");
5255
5256 Parser.Lex();
5257 StringRef Arch;
5258 if (Parser.parseIdentifier(Arch))
5259 return reportParseError("expected arch identifier");
5260
5261 StringRef ArchFeatureName =
5262 StringSwitch<StringRef>(Arch)
5263 .Case("mips1", "mips1")
5264 .Case("mips2", "mips2")
5265 .Case("mips3", "mips3")
5266 .Case("mips4", "mips4")
5267 .Case("mips5", "mips5")
5268 .Case("mips32", "mips32")
5269 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005270 .Case("mips32r3", "mips32r3")
5271 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005272 .Case("mips32r6", "mips32r6")
5273 .Case("mips64", "mips64")
5274 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005275 .Case("mips64r3", "mips64r3")
5276 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005277 .Case("mips64r6", "mips64r6")
5278 .Case("cnmips", "cnmips")
5279 .Case("r4000", "mips3") // This is an implementation of Mips3.
5280 .Default("");
5281
5282 if (ArchFeatureName.empty())
5283 return reportParseError("unsupported architecture");
5284
5285 selectArch(ArchFeatureName);
5286 getTargetStreamer().emitDirectiveSetArch(Arch);
5287 return false;
5288}
5289
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005290bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005291 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005292 Parser.Lex();
5293 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005294 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005295
Matheus Almeida2852af82014-04-22 10:15:54 +00005296 switch (Feature) {
5297 default:
5298 llvm_unreachable("Unimplemented feature");
5299 case Mips::FeatureDSP:
5300 setFeatureBits(Mips::FeatureDSP, "dsp");
5301 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005302 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005303 case Mips::FeatureMicroMips:
5304 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005305 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005306 case Mips::FeatureMips1:
5307 selectArch("mips1");
5308 getTargetStreamer().emitDirectiveSetMips1();
5309 break;
5310 case Mips::FeatureMips2:
5311 selectArch("mips2");
5312 getTargetStreamer().emitDirectiveSetMips2();
5313 break;
5314 case Mips::FeatureMips3:
5315 selectArch("mips3");
5316 getTargetStreamer().emitDirectiveSetMips3();
5317 break;
5318 case Mips::FeatureMips4:
5319 selectArch("mips4");
5320 getTargetStreamer().emitDirectiveSetMips4();
5321 break;
5322 case Mips::FeatureMips5:
5323 selectArch("mips5");
5324 getTargetStreamer().emitDirectiveSetMips5();
5325 break;
5326 case Mips::FeatureMips32:
5327 selectArch("mips32");
5328 getTargetStreamer().emitDirectiveSetMips32();
5329 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005330 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005331 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005332 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005333 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005334 case Mips::FeatureMips32r3:
5335 selectArch("mips32r3");
5336 getTargetStreamer().emitDirectiveSetMips32R3();
5337 break;
5338 case Mips::FeatureMips32r5:
5339 selectArch("mips32r5");
5340 getTargetStreamer().emitDirectiveSetMips32R5();
5341 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005342 case Mips::FeatureMips32r6:
5343 selectArch("mips32r6");
5344 getTargetStreamer().emitDirectiveSetMips32R6();
5345 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005346 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005347 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005348 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005349 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005350 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005351 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005352 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005353 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005354 case Mips::FeatureMips64r3:
5355 selectArch("mips64r3");
5356 getTargetStreamer().emitDirectiveSetMips64R3();
5357 break;
5358 case Mips::FeatureMips64r5:
5359 selectArch("mips64r5");
5360 getTargetStreamer().emitDirectiveSetMips64R5();
5361 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005362 case Mips::FeatureMips64r6:
5363 selectArch("mips64r6");
5364 getTargetStreamer().emitDirectiveSetMips64R6();
5365 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005366 }
5367 return false;
5368}
5369
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005370bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005371 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005372 if (getLexer().isNot(AsmToken::Comma)) {
5373 SMLoc Loc = getLexer().getLoc();
5374 Parser.eatToEndOfStatement();
5375 return Error(Loc, ErrorStr);
5376 }
5377
Matheus Almeida2852af82014-04-22 10:15:54 +00005378 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005379 return true;
5380}
5381
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005382// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5383// In this class, it is only used for .cprestore.
5384// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5385// MipsTargetELFStreamer and MipsAsmParser.
5386bool MipsAsmParser::isPicAndNotNxxAbi() {
5387 return inPicMode() && !(isABI_N32() || isABI_N64());
5388}
5389
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005390bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005391 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005392 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005393
Toma Tabacudde4c462014-11-06 10:02:45 +00005394 if (inMips16Mode()) {
5395 reportParseError(".cpload is not supported in Mips16 mode");
5396 return false;
5397 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005398
David Blaikie960ea3f2014-06-08 16:18:35 +00005399 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005400 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005401 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5402 reportParseError("expected register containing function address");
5403 return false;
5404 }
5405
David Blaikie960ea3f2014-06-08 16:18:35 +00005406 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5407 if (!RegOpnd.isGPRAsmReg()) {
5408 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005409 return false;
5410 }
5411
Toma Tabacudde4c462014-11-06 10:02:45 +00005412 // If this is not the end of the statement, report an error.
5413 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5414 reportParseError("unexpected token, expected end of statement");
5415 return false;
5416 }
5417
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005418 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005419 return false;
5420}
5421
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005422bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5423 MCAsmParser &Parser = getParser();
5424
5425 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5426 // is used in non-PIC mode.
5427
5428 if (inMips16Mode()) {
5429 reportParseError(".cprestore is not supported in Mips16 mode");
5430 return false;
5431 }
5432
5433 // Get the stack offset value.
5434 const MCExpr *StackOffset;
5435 int64_t StackOffsetVal;
5436 if (Parser.parseExpression(StackOffset)) {
5437 reportParseError("expected stack offset value");
5438 return false;
5439 }
5440
5441 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5442 reportParseError("stack offset is not an absolute expression");
5443 return false;
5444 }
5445
5446 if (StackOffsetVal < 0) {
5447 Warning(Loc, ".cprestore with negative stack offset has no effect");
5448 IsCpRestoreSet = false;
5449 } else {
5450 IsCpRestoreSet = true;
5451 CpRestoreOffset = StackOffsetVal;
5452 }
5453
5454 // If this is not the end of the statement, report an error.
5455 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5456 reportParseError("unexpected token, expected end of statement");
5457 return false;
5458 }
5459
5460 // Store the $gp on the stack.
5461 SmallVector<MCInst, 3> StoreInsts;
5462 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5463 StoreInsts);
5464
5465 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5466 Parser.Lex(); // Consume the EndOfStatement.
5467 return false;
5468}
5469
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005470bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005471 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005472 unsigned FuncReg;
5473 unsigned Save;
5474 bool SaveIsReg = true;
5475
Matheus Almeida7e815762014-06-18 13:08:59 +00005476 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005477 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005478 if (ResTy == MatchOperand_NoMatch) {
5479 reportParseError("expected register containing function address");
5480 Parser.eatToEndOfStatement();
5481 return false;
5482 }
5483
5484 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5485 if (!FuncRegOpnd.isGPRAsmReg()) {
5486 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5487 Parser.eatToEndOfStatement();
5488 return false;
5489 }
5490
5491 FuncReg = FuncRegOpnd.getGPR32Reg();
5492 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005493
Toma Tabacu65f10572014-09-16 15:00:52 +00005494 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005495 return true;
5496
Toma Tabacu13964452014-09-04 13:23:44 +00005497 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005498 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005499 const MCExpr *OffsetExpr;
5500 int64_t OffsetVal;
5501 SMLoc ExprLoc = getLexer().getLoc();
5502
5503 if (Parser.parseExpression(OffsetExpr) ||
5504 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5505 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005506 Parser.eatToEndOfStatement();
5507 return false;
5508 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005509
5510 Save = OffsetVal;
5511 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005512 } else {
5513 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5514 if (!SaveOpnd.isGPRAsmReg()) {
5515 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5516 Parser.eatToEndOfStatement();
5517 return false;
5518 }
5519 Save = SaveOpnd.getGPR32Reg();
5520 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005521
Toma Tabacu65f10572014-09-16 15:00:52 +00005522 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005523 return true;
5524
Toma Tabacu8874eac2015-02-18 13:46:53 +00005525 const MCExpr *Expr;
5526 if (Parser.parseExpression(Expr)) {
5527 reportParseError("expected expression");
5528 return false;
5529 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005530
Toma Tabacu8874eac2015-02-18 13:46:53 +00005531 if (Expr->getKind() != MCExpr::SymbolRef) {
5532 reportParseError("expected symbol");
5533 return false;
5534 }
5535 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5536
Daniel Sandersf173dda2015-09-22 10:50:09 +00005537 CpSaveLocation = Save;
5538 CpSaveLocationIsRegister = SaveIsReg;
5539
Toma Tabacu8874eac2015-02-18 13:46:53 +00005540 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5541 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005542 return false;
5543}
5544
Daniel Sandersf173dda2015-09-22 10:50:09 +00005545bool MipsAsmParser::parseDirectiveCPReturn() {
5546 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5547 CpSaveLocationIsRegister);
5548 return false;
5549}
5550
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005551bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005552 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005553 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5554 const AsmToken &Tok = Parser.getTok();
5555
5556 if (Tok.getString() == "2008") {
5557 Parser.Lex();
5558 getTargetStreamer().emitDirectiveNaN2008();
5559 return false;
5560 } else if (Tok.getString() == "legacy") {
5561 Parser.Lex();
5562 getTargetStreamer().emitDirectiveNaNLegacy();
5563 return false;
5564 }
5565 }
5566 // If we don't recognize the option passed to the .nan
5567 // directive (e.g. no option or unknown option), emit an error.
5568 reportParseError("invalid option in .nan directive");
5569 return false;
5570}
5571
Jack Carter0b744b32012-10-04 02:29:46 +00005572bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005573 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005574 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005575 const AsmToken &Tok = Parser.getTok();
5576
5577 if (Tok.getString() == "noat") {
5578 return parseSetNoAtDirective();
5579 } else if (Tok.getString() == "at") {
5580 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005581 } else if (Tok.getString() == "arch") {
5582 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005583 } else if (Tok.getString() == "fp") {
5584 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005585 } else if (Tok.getString() == "oddspreg") {
5586 return parseSetOddSPRegDirective();
5587 } else if (Tok.getString() == "nooddspreg") {
5588 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005589 } else if (Tok.getString() == "pop") {
5590 return parseSetPopDirective();
5591 } else if (Tok.getString() == "push") {
5592 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005593 } else if (Tok.getString() == "reorder") {
5594 return parseSetReorderDirective();
5595 } else if (Tok.getString() == "noreorder") {
5596 return parseSetNoReorderDirective();
5597 } else if (Tok.getString() == "macro") {
5598 return parseSetMacroDirective();
5599 } else if (Tok.getString() == "nomacro") {
5600 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005601 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005602 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005603 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005604 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005605 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005606 getTargetStreamer().emitDirectiveSetNoMicroMips();
5607 Parser.eatToEndOfStatement();
5608 return false;
5609 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005610 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005611 } else if (Tok.getString() == "mips0") {
5612 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005613 } else if (Tok.getString() == "mips1") {
5614 return parseSetFeature(Mips::FeatureMips1);
5615 } else if (Tok.getString() == "mips2") {
5616 return parseSetFeature(Mips::FeatureMips2);
5617 } else if (Tok.getString() == "mips3") {
5618 return parseSetFeature(Mips::FeatureMips3);
5619 } else if (Tok.getString() == "mips4") {
5620 return parseSetFeature(Mips::FeatureMips4);
5621 } else if (Tok.getString() == "mips5") {
5622 return parseSetFeature(Mips::FeatureMips5);
5623 } else if (Tok.getString() == "mips32") {
5624 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005625 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005626 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005627 } else if (Tok.getString() == "mips32r3") {
5628 return parseSetFeature(Mips::FeatureMips32r3);
5629 } else if (Tok.getString() == "mips32r5") {
5630 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005631 } else if (Tok.getString() == "mips32r6") {
5632 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005633 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005634 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005635 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005636 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005637 } else if (Tok.getString() == "mips64r3") {
5638 return parseSetFeature(Mips::FeatureMips64r3);
5639 } else if (Tok.getString() == "mips64r5") {
5640 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005641 } else if (Tok.getString() == "mips64r6") {
5642 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005643 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005644 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005645 } else if (Tok.getString() == "nodsp") {
5646 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005647 } else if (Tok.getString() == "msa") {
5648 return parseSetMsaDirective();
5649 } else if (Tok.getString() == "nomsa") {
5650 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005651 } else if (Tok.getString() == "softfloat") {
5652 return parseSetSoftFloatDirective();
5653 } else if (Tok.getString() == "hardfloat") {
5654 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005655 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005656 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005657 parseSetAssignment();
5658 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005659 }
Jack Carter07c818d2013-01-25 01:31:34 +00005660
Jack Carter0b744b32012-10-04 02:29:46 +00005661 return true;
5662}
5663
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005664/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005665/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005666bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005667 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005668 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5669 for (;;) {
5670 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005671 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005672 return true;
5673
5674 getParser().getStreamer().EmitValue(Value, Size);
5675
5676 if (getLexer().is(AsmToken::EndOfStatement))
5677 break;
5678
Jack Carter07c818d2013-01-25 01:31:34 +00005679 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005680 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005681 Parser.Lex();
5682 }
5683 }
5684
5685 Parser.Lex();
5686 return false;
5687}
5688
Vladimir Medic4c299852013-11-06 11:27:05 +00005689/// parseDirectiveGpWord
5690/// ::= .gpword local_sym
5691bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005692 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005693 const MCExpr *Value;
5694 // EmitGPRel32Value requires an expression, so we are using base class
5695 // method to evaluate the expression.
5696 if (getParser().parseExpression(Value))
5697 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005698 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005699
Vladimir Medice10c1122013-11-13 13:18:04 +00005700 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005701 return Error(getLexer().getLoc(),
5702 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005703 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005704 return false;
5705}
5706
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005707/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005708/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005709bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005710 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005711 const MCExpr *Value;
5712 // EmitGPRel64Value requires an expression, so we are using base class
5713 // method to evaluate the expression.
5714 if (getParser().parseExpression(Value))
5715 return true;
5716 getParser().getStreamer().EmitGPRel64Value(Value);
5717
5718 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005719 return Error(getLexer().getLoc(),
5720 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005721 Parser.Lex(); // Eat EndOfStatement token.
5722 return false;
5723}
5724
Jack Carter0cd3c192014-01-06 23:27:31 +00005725bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005726 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005727 // Get the option token.
5728 AsmToken Tok = Parser.getTok();
5729 // At the moment only identifiers are supported.
5730 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005731 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005732 Parser.eatToEndOfStatement();
5733 return false;
5734 }
5735
5736 StringRef Option = Tok.getIdentifier();
5737
5738 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005739 // MipsAsmParser needs to know if the current PIC mode changes.
5740 IsPicEnabled = false;
5741
Jack Carter0cd3c192014-01-06 23:27:31 +00005742 getTargetStreamer().emitDirectiveOptionPic0();
5743 Parser.Lex();
5744 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5745 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005746 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005747 Parser.eatToEndOfStatement();
5748 }
5749 return false;
5750 }
5751
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005752 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005753 // MipsAsmParser needs to know if the current PIC mode changes.
5754 IsPicEnabled = true;
5755
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005756 getTargetStreamer().emitDirectiveOptionPic2();
5757 Parser.Lex();
5758 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5759 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005760 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005761 Parser.eatToEndOfStatement();
5762 }
5763 return false;
5764 }
5765
Jack Carter0cd3c192014-01-06 23:27:31 +00005766 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005767 Warning(Parser.getTok().getLoc(),
5768 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005769 Parser.eatToEndOfStatement();
5770 return false;
5771}
5772
Toma Tabacu9ca50962015-04-16 09:53:47 +00005773/// parseInsnDirective
5774/// ::= .insn
5775bool MipsAsmParser::parseInsnDirective() {
5776 // If this is not the end of the statement, report an error.
5777 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5778 reportParseError("unexpected token, expected end of statement");
5779 return false;
5780 }
5781
5782 // The actual label marking happens in
5783 // MipsELFStreamer::createPendingLabelRelocs().
5784 getTargetStreamer().emitDirectiveInsn();
5785
5786 getParser().Lex(); // Eat EndOfStatement token.
5787 return false;
5788}
5789
Simon Atanasyanbe186202016-02-11 06:45:54 +00005790/// parseSSectionDirective
5791/// ::= .sbss
5792/// ::= .sdata
5793bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5794 // If this is not the end of the statement, report an error.
5795 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5796 reportParseError("unexpected token, expected end of statement");
5797 return false;
5798 }
5799
5800 MCSection *ELFSection = getContext().getELFSection(
5801 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5802 getParser().getStreamer().SwitchSection(ELFSection);
5803
5804 getParser().Lex(); // Eat EndOfStatement token.
5805 return false;
5806}
5807
Daniel Sanders7e527422014-07-10 13:38:23 +00005808/// parseDirectiveModule
5809/// ::= .module oddspreg
5810/// ::= .module nooddspreg
5811/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005812/// ::= .module softfloat
5813/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005814bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005815 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005816 MCAsmLexer &Lexer = getLexer();
5817 SMLoc L = Lexer.getLoc();
5818
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005819 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005820 // TODO : get a better message.
5821 reportParseError(".module directive must appear before any code");
5822 return false;
5823 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005824
Toma Tabacuc405c822015-01-23 10:40:19 +00005825 StringRef Option;
5826 if (Parser.parseIdentifier(Option)) {
5827 reportParseError("expected .module option identifier");
5828 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005829 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005830
Toma Tabacuc405c822015-01-23 10:40:19 +00005831 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005832 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005833
Toma Tabacu3c499582015-06-25 10:56:57 +00005834 // Synchronize the abiflags information with the FeatureBits information we
5835 // changed above.
5836 getTargetStreamer().updateABIInfo(*this);
5837
5838 // If printing assembly, use the recently updated abiflags information.
5839 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5840 // emitted at the end).
5841 getTargetStreamer().emitDirectiveModuleOddSPReg();
5842
Toma Tabacuc405c822015-01-23 10:40:19 +00005843 // If this is not the end of the statement, report an error.
5844 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5845 reportParseError("unexpected token, expected end of statement");
5846 return false;
5847 }
5848
5849 return false; // parseDirectiveModule has finished successfully.
5850 } else if (Option == "nooddspreg") {
5851 if (!isABI_O32()) {
5852 Error(L, "'.module nooddspreg' requires the O32 ABI");
5853 return false;
5854 }
5855
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005856 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005857
Toma Tabacu3c499582015-06-25 10:56:57 +00005858 // Synchronize the abiflags information with the FeatureBits information we
5859 // changed above.
5860 getTargetStreamer().updateABIInfo(*this);
5861
5862 // If printing assembly, use the recently updated abiflags information.
5863 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5864 // emitted at the end).
5865 getTargetStreamer().emitDirectiveModuleOddSPReg();
5866
Toma Tabacuc405c822015-01-23 10:40:19 +00005867 // If this is not the end of the statement, report an error.
5868 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5869 reportParseError("unexpected token, expected end of statement");
5870 return false;
5871 }
5872
5873 return false; // parseDirectiveModule has finished successfully.
5874 } else if (Option == "fp") {
5875 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005876 } else if (Option == "softfloat") {
5877 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5878
5879 // Synchronize the ABI Flags information with the FeatureBits information we
5880 // updated above.
5881 getTargetStreamer().updateABIInfo(*this);
5882
5883 // If printing assembly, use the recently updated ABI Flags information.
5884 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5885 // emitted later).
5886 getTargetStreamer().emitDirectiveModuleSoftFloat();
5887
5888 // If this is not the end of the statement, report an error.
5889 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5890 reportParseError("unexpected token, expected end of statement");
5891 return false;
5892 }
5893
5894 return false; // parseDirectiveModule has finished successfully.
5895 } else if (Option == "hardfloat") {
5896 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5897
5898 // Synchronize the ABI Flags information with the FeatureBits information we
5899 // updated above.
5900 getTargetStreamer().updateABIInfo(*this);
5901
5902 // If printing assembly, use the recently updated ABI Flags information.
5903 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5904 // emitted later).
5905 getTargetStreamer().emitDirectiveModuleHardFloat();
5906
5907 // If this is not the end of the statement, report an error.
5908 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5909 reportParseError("unexpected token, expected end of statement");
5910 return false;
5911 }
5912
5913 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005914 } else {
5915 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5916 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005917}
5918
5919/// parseDirectiveModuleFP
5920/// ::= =32
5921/// ::= =xx
5922/// ::= =64
5923bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005924 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005925 MCAsmLexer &Lexer = getLexer();
5926
5927 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005928 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005929 return false;
5930 }
5931 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005932
Daniel Sanders7e527422014-07-10 13:38:23 +00005933 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005934 if (!parseFpABIValue(FpABI, ".module"))
5935 return false;
5936
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005937 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005938 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005939 return false;
5940 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005941
Toma Tabacua64e5402015-06-25 12:44:38 +00005942 // Synchronize the abiflags information with the FeatureBits information we
5943 // changed above.
5944 getTargetStreamer().updateABIInfo(*this);
5945
5946 // If printing assembly, use the recently updated abiflags information.
5947 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5948 // emitted at the end).
5949 getTargetStreamer().emitDirectiveModuleFP();
5950
Daniel Sanders7e527422014-07-10 13:38:23 +00005951 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005952 return false;
5953}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005954
Daniel Sanders7e527422014-07-10 13:38:23 +00005955bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005956 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005957 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005958 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005959 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005960
5961 if (Lexer.is(AsmToken::Identifier)) {
5962 StringRef Value = Parser.getTok().getString();
5963 Parser.Lex();
5964
5965 if (Value != "xx") {
5966 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5967 return false;
5968 }
5969
5970 if (!isABI_O32()) {
5971 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5972 return false;
5973 }
5974
Daniel Sanders7e527422014-07-10 13:38:23 +00005975 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005976 if (ModuleLevelOptions) {
5977 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5978 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5979 } else {
5980 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5981 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5982 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005983 return true;
5984 }
5985
5986 if (Lexer.is(AsmToken::Integer)) {
5987 unsigned Value = Parser.getTok().getIntVal();
5988 Parser.Lex();
5989
5990 if (Value != 32 && Value != 64) {
5991 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5992 return false;
5993 }
5994
5995 if (Value == 32) {
5996 if (!isABI_O32()) {
5997 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5998 return false;
5999 }
6000
Daniel Sanders7e527422014-07-10 13:38:23 +00006001 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006002 if (ModuleLevelOptions) {
6003 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6004 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6005 } else {
6006 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6007 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6008 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006009 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006010 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006011 if (ModuleLevelOptions) {
6012 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6013 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6014 } else {
6015 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6016 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6017 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006018 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006019
Daniel Sanders7e527422014-07-10 13:38:23 +00006020 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006021 }
6022
6023 return false;
6024}
6025
Jack Carter0b744b32012-10-04 02:29:46 +00006026bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006027 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006028 StringRef IDVal = DirectiveID.getString();
6029
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006030 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006031 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006032 if (IDVal == ".cprestore")
6033 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006034 if (IDVal == ".dword") {
6035 parseDataDirective(8, DirectiveID.getLoc());
6036 return false;
6037 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006038 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006039 StringRef SymbolName;
6040
6041 if (Parser.parseIdentifier(SymbolName)) {
6042 reportParseError("expected identifier after .ent");
6043 return false;
6044 }
6045
6046 // There's an undocumented extension that allows an integer to
6047 // follow the name of the procedure which AFAICS is ignored by GAS.
6048 // Example: .ent foo,2
6049 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6050 if (getLexer().isNot(AsmToken::Comma)) {
6051 // Even though we accept this undocumented extension for compatibility
6052 // reasons, the additional integer argument does not actually change
6053 // the behaviour of the '.ent' directive, so we would like to discourage
6054 // its use. We do this by not referring to the extended version in
6055 // error messages which are not directly related to its use.
6056 reportParseError("unexpected token, expected end of statement");
6057 return false;
6058 }
6059 Parser.Lex(); // Eat the comma.
6060 const MCExpr *DummyNumber;
6061 int64_t DummyNumberVal;
6062 // If the user was explicitly trying to use the extended version,
6063 // we still give helpful extension-related error messages.
6064 if (Parser.parseExpression(DummyNumber)) {
6065 reportParseError("expected number after comma");
6066 return false;
6067 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006068 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006069 reportParseError("expected an absolute expression after comma");
6070 return false;
6071 }
6072 }
6073
6074 // If this is not the end of the statement, report an error.
6075 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6076 reportParseError("unexpected token, expected end of statement");
6077 return false;
6078 }
6079
Jim Grosbach6f482002015-05-18 18:43:14 +00006080 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006081
6082 getTargetStreamer().emitDirectiveEnt(*Sym);
6083 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006084 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006085 return false;
6086 }
6087
Jack Carter07c818d2013-01-25 01:31:34 +00006088 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006089 StringRef SymbolName;
6090
6091 if (Parser.parseIdentifier(SymbolName)) {
6092 reportParseError("expected identifier after .end");
6093 return false;
6094 }
6095
6096 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6097 reportParseError("unexpected token, expected end of statement");
6098 return false;
6099 }
6100
6101 if (CurrentFn == nullptr) {
6102 reportParseError(".end used without .ent");
6103 return false;
6104 }
6105
6106 if ((SymbolName != CurrentFn->getName())) {
6107 reportParseError(".end symbol does not match .ent symbol");
6108 return false;
6109 }
6110
6111 getTargetStreamer().emitDirectiveEnd(SymbolName);
6112 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006113 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006114 return false;
6115 }
6116
Jack Carter07c818d2013-01-25 01:31:34 +00006117 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006118 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6119 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006120 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006121 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6122 reportParseError("expected stack register");
6123 return false;
6124 }
6125
6126 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6127 if (!StackRegOpnd.isGPRAsmReg()) {
6128 reportParseError(StackRegOpnd.getStartLoc(),
6129 "expected general purpose register");
6130 return false;
6131 }
6132 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6133
6134 if (Parser.getTok().is(AsmToken::Comma))
6135 Parser.Lex();
6136 else {
6137 reportParseError("unexpected token, expected comma");
6138 return false;
6139 }
6140
6141 // Parse the frame size.
6142 const MCExpr *FrameSize;
6143 int64_t FrameSizeVal;
6144
6145 if (Parser.parseExpression(FrameSize)) {
6146 reportParseError("expected frame size value");
6147 return false;
6148 }
6149
Jim Grosbach13760bd2015-05-30 01:25:56 +00006150 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006151 reportParseError("frame size not an absolute expression");
6152 return false;
6153 }
6154
6155 if (Parser.getTok().is(AsmToken::Comma))
6156 Parser.Lex();
6157 else {
6158 reportParseError("unexpected token, expected comma");
6159 return false;
6160 }
6161
6162 // Parse the return register.
6163 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006164 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006165 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6166 reportParseError("expected return register");
6167 return false;
6168 }
6169
6170 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6171 if (!ReturnRegOpnd.isGPRAsmReg()) {
6172 reportParseError(ReturnRegOpnd.getStartLoc(),
6173 "expected general purpose register");
6174 return false;
6175 }
6176
6177 // If this is not the end of the statement, report an error.
6178 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6179 reportParseError("unexpected token, expected end of statement");
6180 return false;
6181 }
6182
6183 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6184 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006185 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006186 return false;
6187 }
6188
Jack Carter07c818d2013-01-25 01:31:34 +00006189 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00006190 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00006191 }
6192
Daniel Sandersd97a6342014-08-13 10:07:34 +00006193 if (IDVal == ".mask" || IDVal == ".fmask") {
6194 // .mask bitmask, frame_offset
6195 // bitmask: One bit for each register used.
6196 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6197 // first register is expected to be saved.
6198 // Examples:
6199 // .mask 0x80000000, -4
6200 // .fmask 0x80000000, -4
6201 //
Jack Carterbe332172012-09-07 00:48:02 +00006202
Daniel Sandersd97a6342014-08-13 10:07:34 +00006203 // Parse the bitmask
6204 const MCExpr *BitMask;
6205 int64_t BitMaskVal;
6206
6207 if (Parser.parseExpression(BitMask)) {
6208 reportParseError("expected bitmask value");
6209 return false;
6210 }
6211
Jim Grosbach13760bd2015-05-30 01:25:56 +00006212 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006213 reportParseError("bitmask not an absolute expression");
6214 return false;
6215 }
6216
6217 if (Parser.getTok().is(AsmToken::Comma))
6218 Parser.Lex();
6219 else {
6220 reportParseError("unexpected token, expected comma");
6221 return false;
6222 }
6223
6224 // Parse the frame_offset
6225 const MCExpr *FrameOffset;
6226 int64_t FrameOffsetVal;
6227
6228 if (Parser.parseExpression(FrameOffset)) {
6229 reportParseError("expected frame offset value");
6230 return false;
6231 }
6232
Jim Grosbach13760bd2015-05-30 01:25:56 +00006233 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006234 reportParseError("frame offset not an absolute expression");
6235 return false;
6236 }
6237
6238 // If this is not the end of the statement, report an error.
6239 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6240 reportParseError("unexpected token, expected end of statement");
6241 return false;
6242 }
6243
6244 if (IDVal == ".mask")
6245 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6246 else
6247 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006248 return false;
6249 }
6250
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006251 if (IDVal == ".nan")
6252 return parseDirectiveNaN();
6253
Jack Carter07c818d2013-01-25 01:31:34 +00006254 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006255 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006256 return false;
6257 }
6258
Rafael Espindolab59fb732014-03-28 18:50:26 +00006259 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006260 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006261 return false;
6262 }
6263
Jack Carter07c818d2013-01-25 01:31:34 +00006264 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006265 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006266 return false;
6267 }
6268
Scott Egertond1aeb052016-02-15 16:11:51 +00006269 if (IDVal == ".hword") {
6270 parseDataDirective(2, DirectiveID.getLoc());
6271 return false;
6272 }
6273
Jack Carter0cd3c192014-01-06 23:27:31 +00006274 if (IDVal == ".option")
6275 return parseDirectiveOption();
6276
6277 if (IDVal == ".abicalls") {
6278 getTargetStreamer().emitDirectiveAbiCalls();
6279 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006280 Error(Parser.getTok().getLoc(),
6281 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006282 // Clear line
6283 Parser.eatToEndOfStatement();
6284 }
6285 return false;
6286 }
6287
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006288 if (IDVal == ".cpsetup")
6289 return parseDirectiveCPSetup();
6290
Daniel Sandersf173dda2015-09-22 10:50:09 +00006291 if (IDVal == ".cpreturn")
6292 return parseDirectiveCPReturn();
6293
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006294 if (IDVal == ".module")
6295 return parseDirectiveModule();
6296
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006297 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
6298 return parseInternalDirectiveReallowModule();
6299
Toma Tabacu9ca50962015-04-16 09:53:47 +00006300 if (IDVal == ".insn")
6301 return parseInsnDirective();
6302
Simon Atanasyanbe186202016-02-11 06:45:54 +00006303 if (IDVal == ".sbss")
6304 return parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6305 if (IDVal == ".sdata")
6306 return parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6307
Rafael Espindola870c4e92012-01-11 03:56:41 +00006308 return true;
6309}
6310
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006311bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6312 // If this is not the end of the statement, report an error.
6313 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6314 reportParseError("unexpected token, expected end of statement");
6315 return false;
6316 }
6317
6318 getTargetStreamer().reallowModuleDirective();
6319
6320 getParser().Lex(); // Eat EndOfStatement token.
6321 return false;
6322}
6323
Rafael Espindola870c4e92012-01-11 03:56:41 +00006324extern "C" void LLVMInitializeMipsAsmParser() {
6325 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6326 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6327 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6328 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6329}
Jack Carterb4dbc172012-09-05 23:34:03 +00006330
6331#define GET_REGISTER_MATCHER
6332#define GET_MATCHER_IMPLEMENTATION
6333#include "MipsGenAsmMatcher.inc"