blob: 32856550b70aee6a1dc0ebf3a1439baefea95830 [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"
Jack Carterb4dbc172012-09-05 23:34:03 +000025#include "llvm/MC/MCStreamer.h"
26#include "llvm/MC/MCSubtargetInfo.h"
27#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000028#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000029#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000030#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000031#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000032#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000033#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000034#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000035
36using namespace llvm;
37
Chandler Carruthe96dd892014-04-21 22:55:11 +000038#define DEBUG_TYPE "mips-asm-parser"
39
Joey Gouly0e76fa72013-09-12 10:28:05 +000040namespace llvm {
41class MCInstrInfo;
42}
43
Rafael Espindola870c4e92012-01-11 03:56:41 +000044namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000045class MipsAssemblerOptions {
46public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000047 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000048 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000049
Toma Tabacu9db22db2014-09-09 10:15:38 +000050 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000051 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000052 Reorder = Opts->isReorder();
53 Macro = Opts->isMacro();
54 Features = Opts->getFeatures();
55 }
56
Toma Tabacub19cf202015-04-27 13:12:59 +000057 unsigned getATRegIndex() const { return ATReg; }
58 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000059 if (Reg > 31)
60 return false;
61
62 ATReg = Reg;
63 return true;
64 }
Jack Carter0b744b32012-10-04 02:29:46 +000065
Toma Tabacu9db22db2014-09-09 10:15:38 +000066 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000067 void setReorder() { Reorder = true; }
68 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000069
Toma Tabacu9db22db2014-09-09 10:15:38 +000070 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000071 void setMacro() { Macro = true; }
72 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000073
Toma Tabacu465acfd2015-06-09 13:33:26 +000074 const FeatureBitset &getFeatures() const { return Features; }
75 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000076
Daniel Sandersf0df2212014-08-04 12:20:00 +000077 // Set of features that are either architecture features or referenced
78 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
79 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
80 // The reason we need this mask is explained in the selectArch function.
81 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000082 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000083
Jack Carter0b744b32012-10-04 02:29:46 +000084private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000085 unsigned ATReg;
86 bool Reorder;
87 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000088 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000089};
90}
91
Michael Kupersteindb0712f2015-05-26 10:47:10 +000092const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
93 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
94 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
95 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
96 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
97 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
98 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
99 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
100 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
101};
102
Jack Carter0b744b32012-10-04 02:29:46 +0000103namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000104class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000105 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000106 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000107 return static_cast<MipsTargetStreamer &>(TS);
108 }
109
Eric Christophera5762812015-01-26 17:33:46 +0000110 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000111 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000112 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
113 // nullptr, which indicates that no function is currently
114 // selected. This usually happens after an '.end func'
115 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000116 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000117 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000118 bool IsCpRestoreSet;
119 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000120 unsigned CpSaveLocation;
121 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
122 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000123
Daniel Sandersef638fe2014-10-03 15:37:37 +0000124 // Print a warning along with its fix-it message at the given range.
125 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
126 SMRange Range, bool ShowColors = true);
127
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000128#define GET_ASSEMBLER_HEADER
129#include "MipsGenAsmMatcher.inc"
130
Matheus Almeida595fcab2014-06-11 15:05:56 +0000131 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
132
Chad Rosier49963552012-10-13 00:26:04 +0000133 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000134 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000135 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000136 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000137
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000138 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000139 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000140
Toma Tabacu13964452014-09-04 13:23:44 +0000141 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000144
David Blaikie960ea3f2014-06-08 16:18:35 +0000145 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
146 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000147
Craig Topper56c590a2014-04-29 07:58:02 +0000148 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000149
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000150 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
151 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000152 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000153 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000154 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
155 SMLoc S);
156 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
157 OperandMatchResultTy parseImm(OperandVector &Operands);
158 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
159 OperandMatchResultTy parseInvNum(OperandVector &Operands);
160 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
161 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
162 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
163 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000164
David Blaikie960ea3f2014-06-08 16:18:35 +0000165 bool searchSymbolAlias(OperandVector &Operands);
166
Toma Tabacu13964452014-09-04 13:23:44 +0000167 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000168
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000169 enum MacroExpanderResultTy {
170 MER_NotAMacro,
171 MER_Success,
172 MER_Fail,
173 };
Jack Carter30a59822012-10-04 04:03:53 +0000174
Matheus Almeida3813d572014-06-19 14:39:14 +0000175 // Expands assembly pseudo instructions.
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000176 MacroExpanderResultTy
177 tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
178 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000179
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000180 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
181 SmallVectorImpl<MCInst> &Instructions);
182
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000183 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000184 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000185 SmallVectorImpl<MCInst> &Instructions);
186
Toma Tabacuf712ede2015-06-17 14:31:51 +0000187 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
188 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
189 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000190
Toma Tabacu00e98672015-05-01 12:19:27 +0000191 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000192 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000193
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000194 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
195 const MCOperand &Offset, bool Is32BitAddress,
196 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000197
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000198 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
199 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000200
Jack Carter9e65aa32013-03-22 00:05:30 +0000201 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000202 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
203 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000204
205 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
206 SmallVectorImpl<MCInst> &Instructions);
207
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000208 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
209 SmallVectorImpl<MCInst> &Instructions);
210
Toma Tabacue1e460d2015-06-11 10:36:10 +0000211 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
212 SmallVectorImpl<MCInst> &Instructions);
213
Toma Tabacu1a108322015-06-17 13:20:24 +0000214 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
215 SmallVectorImpl<MCInst> &Instructions);
216
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000217 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
218 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
219 const bool Signed);
220
Daniel Sanders6394ee52015-10-15 14:52:58 +0000221 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
222 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000223
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000224 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
225 SmallVectorImpl<MCInst> &Instructions);
226
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000227 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
228 SmallVectorImpl<MCInst> &Instructions);
229 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc,
230 SmallVectorImpl<MCInst> &Instructions);
231 bool expandDRotation(MCInst &Inst, SMLoc IDLoc,
232 SmallVectorImpl<MCInst> &Instructions);
233 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
234 SmallVectorImpl<MCInst> &Instructions);
235
Toma Tabacu234482a2015-03-16 12:03:39 +0000236 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
237 SmallVectorImpl<MCInst> &Instructions);
238
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000239 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000240 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000241
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000242 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
243 SmallVectorImpl<MCInst> &Instructions);
244
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000245 bool reportParseError(Twine ErrorMsg);
246 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000247
Jack Carterb5cf5902013-04-17 00:18:04 +0000248 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000249 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000250
Vladimir Medic4c299852013-11-06 11:27:05 +0000251 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000252
253 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000254 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000255 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000256 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000257 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000258 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000259 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000260 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000261 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000262 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000263 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000264 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000265 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000266
267 bool parseSetAtDirective();
268 bool parseSetNoAtDirective();
269 bool parseSetMacroDirective();
270 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000271 bool parseSetMsaDirective();
272 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000273 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000274 bool parseSetReorderDirective();
275 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000276 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000277 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000278 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000279 bool parseSetOddSPRegDirective();
280 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000281 bool parseSetPopDirective();
282 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000283 bool parseSetSoftFloatDirective();
284 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000285
Jack Carterd76b2372013-03-21 21:44:16 +0000286 bool parseSetAssignment();
287
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000288 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000289 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000290 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000291 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000292 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000293 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
294 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000295
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000296 bool parseInternalDirectiveReallowModule();
297
Jack Carterdc1e35d2012-09-06 20:00:02 +0000298 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000299
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000300 bool eatComma(StringRef ErrorStr);
301
Jack Carter1ac53222013-02-20 23:11:17 +0000302 int matchCPURegisterName(StringRef Symbol);
303
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000304 int matchHWRegsRegisterName(StringRef Symbol);
305
Jack Carter873c7242013-01-12 01:03:14 +0000306 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000307
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000308 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000309
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000310 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000311
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000312 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000313
Jack Carter5dc8ac92013-09-25 23:50:44 +0000314 int matchMSA128RegisterName(StringRef Name);
315
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000316 int matchMSA128CtrlRegisterName(StringRef Name);
317
Jack Carterd0bd6422013-04-18 00:41:53 +0000318 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000319
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000320 unsigned getGPR(int RegNo);
321
Toma Tabacu89a712b2015-04-15 10:48:56 +0000322 /// Returns the internal register number for the current AT. Also checks if
323 /// the current AT is unavailable (set to $0) and gives an error if it is.
324 /// This should be used in pseudo-instruction expansions which need AT.
325 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000326
327 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000328 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000329
330 // Helper function that checks if the value of a vector index is within the
331 // boundaries of accepted values for each RegisterKind
332 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
333 bool validateMSAIndex(int Val, int RegKind);
334
Daniel Sandersf0df2212014-08-04 12:20:00 +0000335 // Selects a new architecture by updating the FeatureBits with the necessary
336 // info including implied dependencies.
337 // Internally, it clears all the feature bits related to *any* architecture
338 // and selects the new one using the ToggleFeature functionality of the
339 // MCSubtargetInfo object that handles implied dependencies. The reason we
340 // clear all the arch related bits manually is because ToggleFeature only
341 // clears the features that imply the feature being cleared and not the
342 // features implied by the feature being cleared. This is easier to see
343 // with an example:
344 // --------------------------------------------------
345 // | Feature | Implies |
346 // | -------------------------------------------------|
347 // | FeatureMips1 | None |
348 // | FeatureMips2 | FeatureMips1 |
349 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
350 // | FeatureMips4 | FeatureMips3 |
351 // | ... | |
352 // --------------------------------------------------
353 //
354 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
355 // FeatureMipsGP64 | FeatureMips1)
356 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
357 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000358 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000359 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000360 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
361 STI.setFeatureBits(FeatureBits);
362 setAvailableFeatures(
363 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000364 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000365 }
366
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000367 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000368 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000369 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000370 setAvailableFeatures(
371 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000372 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000373 }
374 }
375
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000376 void clearFeatureBits(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 Tabacufc97d8a2015-06-30 12:41:33 +0000385 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
386 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000387 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000388 }
389
390 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
391 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000392 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000393 }
394
Rafael Espindola870c4e92012-01-11 03:56:41 +0000395public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000396 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000397 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000398#define GET_OPERAND_DIAGNOSTIC_TYPES
399#include "MipsGenAsmMatcher.inc"
400#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000401 };
402
Akira Hatanakab11ef082015-11-14 06:35:56 +0000403 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000404 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000405 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000406 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
407 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000408 MCAsmParserExtension::Initialize(parser);
409
Toma Tabacu11e14a92015-04-21 11:50:52 +0000410 parser.addAliasForDirective(".asciiz", ".asciz");
411
Jack Carterb4dbc172012-09-05 23:34:03 +0000412 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000413 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000414
Toma Tabacu9db22db2014-09-09 10:15:38 +0000415 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000416 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000417 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000418
Toma Tabacu9db22db2014-09-09 10:15:38 +0000419 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000420 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000421 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000422
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000423 getTargetStreamer().updateABIInfo(*this);
424
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000425 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000426 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000427
428 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000429
Daniel Sandersa6994442015-08-18 12:33:54 +0000430 IsPicEnabled =
431 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
432
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000433 IsCpRestoreSet = false;
434 CpRestoreOffset = -1;
435
Daniel Sanders50f17232015-09-15 16:17:27 +0000436 Triple TheTriple(sti.getTargetTriple());
437 if ((TheTriple.getArch() == Triple::mips) ||
438 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000439 IsLittleEndian = false;
440 else
441 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000442 }
443
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000444 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
445 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
446
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000447 bool isGP64bit() const {
448 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
449 }
450 bool isFP64bit() const {
451 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
452 }
Eric Christophera5762812015-01-26 17:33:46 +0000453 const MipsABIInfo &getABI() const { return ABI; }
454 bool isABI_N32() const { return ABI.IsN32(); }
455 bool isABI_N64() const { return ABI.IsN64(); }
456 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000457 bool isABI_FPXX() const {
458 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
459 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000460
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000461 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000462 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000463 }
464
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000465 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000466 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000467 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000468 bool hasMips1() const {
469 return getSTI().getFeatureBits()[Mips::FeatureMips1];
470 }
471 bool hasMips2() const {
472 return getSTI().getFeatureBits()[Mips::FeatureMips2];
473 }
474 bool hasMips3() const {
475 return getSTI().getFeatureBits()[Mips::FeatureMips3];
476 }
477 bool hasMips4() const {
478 return getSTI().getFeatureBits()[Mips::FeatureMips4];
479 }
480 bool hasMips5() const {
481 return getSTI().getFeatureBits()[Mips::FeatureMips5];
482 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000483 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000484 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000485 }
486 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000487 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000488 }
489 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000490 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000491 }
492 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000493 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000494 }
Daniel Sanders17793142015-02-18 16:24:50 +0000495 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000496 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000497 }
498 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000500 }
501 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000502 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000503 }
504 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000505 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000506 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000507 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000508 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000509 }
510 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000511 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000512 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000513
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000514 bool hasDSP() const {
515 return getSTI().getFeatureBits()[Mips::FeatureDSP];
516 }
517 bool hasDSPR2() const {
518 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
519 }
520 bool hasDSPR3() const {
521 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
522 }
523 bool hasMSA() const {
524 return getSTI().getFeatureBits()[Mips::FeatureMSA];
525 }
Kai Nackee0245392015-01-27 19:11:28 +0000526 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000527 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000528 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000529
Daniel Sandersa6994442015-08-18 12:33:54 +0000530 bool inPicMode() {
531 return IsPicEnabled;
532 }
533
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000534 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000535 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000536 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000537
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000538 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000539 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000540 }
541
Eric Christophere8ae3e32015-05-07 23:10:21 +0000542 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000543 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000544 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000545
Toma Tabacud9d344b2015-04-27 14:05:04 +0000546 /// Warn if RegIndex is the same as the current AT.
547 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000548
549 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000550
551 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000552};
553}
554
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000555namespace {
556
557/// MipsOperand - Instances of this class represent a parsed Mips machine
558/// instruction.
559class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000560public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000561 /// Broad categories of register classes
562 /// The exact class is finalized by the render method.
563 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000564 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000565 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000566 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000567 RegKind_FCC = 4, /// FCC
568 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
569 RegKind_MSACtrl = 16, /// MSA control registers
570 RegKind_COP2 = 32, /// COP2
571 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
572 /// context).
573 RegKind_CCR = 128, /// CCR
574 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000575 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000576 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000577 /// Potentially any (e.g. $1)
578 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
579 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000580 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000581 };
582
583private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000584 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000585 k_Immediate, /// An immediate (possibly involving symbol references)
586 k_Memory, /// Base + Offset Memory Address
587 k_PhysRegister, /// A physical register from the Mips namespace
588 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000589 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000590 k_RegList, /// A physical register list
591 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000592 } Kind;
593
David Blaikie960ea3f2014-06-08 16:18:35 +0000594public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000595 MipsOperand(KindTy K, MipsAsmParser &Parser)
596 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
597
David Blaikie960ea3f2014-06-08 16:18:35 +0000598private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000599 /// For diagnostics, and checking the assembler temporary
600 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000601
Eric Christopher8996c5d2013-03-15 00:42:55 +0000602 struct Token {
603 const char *Data;
604 unsigned Length;
605 };
606
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000607 struct PhysRegOp {
608 unsigned Num; /// Register Number
609 };
610
611 struct RegIdxOp {
612 unsigned Index; /// Index into the register class
613 RegKind Kind; /// Bitfield of the kinds it could possibly be
614 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000615 };
616
617 struct ImmOp {
618 const MCExpr *Val;
619 };
620
621 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000622 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000623 const MCExpr *Off;
624 };
625
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000626 struct RegListOp {
627 SmallVector<unsigned, 10> *List;
628 };
629
Jack Carterb4dbc172012-09-05 23:34:03 +0000630 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000631 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000632 struct PhysRegOp PhysReg;
633 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000634 struct ImmOp Imm;
635 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000636 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000637 };
638
639 SMLoc StartLoc, EndLoc;
640
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000641 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000642 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
643 const MCRegisterInfo *RegInfo,
644 SMLoc S, SMLoc E,
645 MipsAsmParser &Parser) {
646 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000647 Op->RegIdx.Index = Index;
648 Op->RegIdx.RegInfo = RegInfo;
649 Op->RegIdx.Kind = RegKind;
650 Op->StartLoc = S;
651 Op->EndLoc = E;
652 return Op;
653 }
654
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000655public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000656 /// Coerce the register to GPR32 and return the real register for the current
657 /// target.
658 unsigned getGPR32Reg() const {
659 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000660 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000661 unsigned ClassID = Mips::GPR32RegClassID;
662 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000663 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000664
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000665 /// Coerce the register to GPR32 and return the real register for the current
666 /// target.
667 unsigned getGPRMM16Reg() const {
668 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
669 unsigned ClassID = Mips::GPR32RegClassID;
670 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
671 }
672
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000673 /// Coerce the register to GPR64 and return the real register for the current
674 /// target.
675 unsigned getGPR64Reg() const {
676 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
677 unsigned ClassID = Mips::GPR64RegClassID;
678 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000679 }
680
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000681private:
682 /// Coerce the register to AFGR64 and return the real register for the current
683 /// target.
684 unsigned getAFGR64Reg() const {
685 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
686 if (RegIdx.Index % 2 != 0)
687 AsmParser.Warning(StartLoc, "Float register should be even.");
688 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
689 .getRegister(RegIdx.Index / 2);
690 }
691
692 /// Coerce the register to FGR64 and return the real register for the current
693 /// target.
694 unsigned getFGR64Reg() const {
695 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
696 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
697 .getRegister(RegIdx.Index);
698 }
699
700 /// Coerce the register to FGR32 and return the real register for the current
701 /// target.
702 unsigned getFGR32Reg() const {
703 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
704 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
705 .getRegister(RegIdx.Index);
706 }
707
708 /// Coerce the register to FGRH32 and return the real register for the current
709 /// target.
710 unsigned getFGRH32Reg() const {
711 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
712 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
713 .getRegister(RegIdx.Index);
714 }
715
716 /// Coerce the register to FCC and return the real register for the current
717 /// target.
718 unsigned getFCCReg() const {
719 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
720 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
721 .getRegister(RegIdx.Index);
722 }
723
724 /// Coerce the register to MSA128 and return the real register for the current
725 /// target.
726 unsigned getMSA128Reg() const {
727 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
728 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
729 // identical
730 unsigned ClassID = Mips::MSA128BRegClassID;
731 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
732 }
733
734 /// Coerce the register to MSACtrl and return the real register for the
735 /// current target.
736 unsigned getMSACtrlReg() const {
737 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
738 unsigned ClassID = Mips::MSACtrlRegClassID;
739 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
740 }
741
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000742 /// Coerce the register to COP0 and return the real register for the
743 /// current target.
744 unsigned getCOP0Reg() const {
745 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
746 unsigned ClassID = Mips::COP0RegClassID;
747 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
748 }
749
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000750 /// Coerce the register to COP2 and return the real register for the
751 /// current target.
752 unsigned getCOP2Reg() const {
753 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
754 unsigned ClassID = Mips::COP2RegClassID;
755 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
756 }
757
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000758 /// Coerce the register to COP3 and return the real register for the
759 /// current target.
760 unsigned getCOP3Reg() const {
761 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
762 unsigned ClassID = Mips::COP3RegClassID;
763 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
764 }
765
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000766 /// Coerce the register to ACC64DSP and return the real register for the
767 /// current target.
768 unsigned getACC64DSPReg() const {
769 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
770 unsigned ClassID = Mips::ACC64DSPRegClassID;
771 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
772 }
773
774 /// Coerce the register to HI32DSP and return the real register for the
775 /// current target.
776 unsigned getHI32DSPReg() const {
777 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
778 unsigned ClassID = Mips::HI32DSPRegClassID;
779 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
780 }
781
782 /// Coerce the register to LO32DSP and return the real register for the
783 /// current target.
784 unsigned getLO32DSPReg() const {
785 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
786 unsigned ClassID = Mips::LO32DSPRegClassID;
787 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
788 }
789
790 /// Coerce the register to CCR and return the real register for the
791 /// current target.
792 unsigned getCCRReg() const {
793 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
794 unsigned ClassID = Mips::CCRRegClassID;
795 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
796 }
797
798 /// Coerce the register to HWRegs and return the real register for the
799 /// current target.
800 unsigned getHWRegsReg() const {
801 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
802 unsigned ClassID = Mips::HWRegsRegClassID;
803 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
804 }
805
806public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000807 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000808 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000809 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000810 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000811 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000812 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000813 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000814 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000815 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000816
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000817 void addRegOperands(MCInst &Inst, unsigned N) const {
818 llvm_unreachable("Use a custom parser instead");
819 }
820
Daniel Sanders21bce302014-04-01 12:35:23 +0000821 /// Render the operand to an MCInst as a GPR32
822 /// Asserts if the wrong number of operands are requested, or the operand
823 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000824 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
825 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000826 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000827 }
828
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000829 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
830 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000831 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000832 }
833
Jozef Kolek1904fa22014-11-24 14:25:53 +0000834 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
835 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000836 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000837 }
838
Zoran Jovanovic41688672015-02-10 16:36:20 +0000839 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
840 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000841 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000842 }
843
Daniel Sanders21bce302014-04-01 12:35:23 +0000844 /// Render the operand to an MCInst as a GPR64
845 /// Asserts if the wrong number of operands are requested, or the operand
846 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000847 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
848 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000849 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 }
851
852 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
853 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000854 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000855 }
856
857 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
858 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000859 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000860 }
861
862 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
863 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000864 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000865 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000866 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000867 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
868 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000869 }
870
871 void addFGRH32AsmRegOperands(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(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000874 }
875
876 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
877 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000878 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000879 }
880
881 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
882 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000883 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000884 }
885
886 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
887 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000888 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000889 }
890
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000891 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
892 assert(N == 1 && "Invalid number of operands!");
893 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
894 }
895
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000896 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
897 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000898 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000899 }
900
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000901 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
902 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000903 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000904 }
905
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000906 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
907 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000908 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000909 }
910
911 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
912 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000913 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000914 }
915
916 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
917 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000918 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000919 }
920
921 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
922 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000923 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000924 }
925
926 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
927 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000928 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000929 }
930
Daniel Sandersea4f6532015-11-06 12:22:31 +0000931 template <unsigned Bits, int Offset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000932 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
933 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000934 uint64_t Imm = getConstantImm() - Offset;
935 Imm &= (1 << Bits) - 1;
936 Imm += Offset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000937 Inst.addOperand(MCOperand::createImm(Imm));
938 }
939
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000940 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000941 assert(N == 1 && "Invalid number of operands!");
942 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000943 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000944 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000945
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000946 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000947 assert(N == 2 && "Invalid number of operands!");
948
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000949 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
950 ? getMemBase()->getGPR64Reg()
951 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000952
953 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000954 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000955 }
956
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000957 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
958 assert(N == 2 && "Invalid number of operands!");
959
Jim Grosbache9119e42015-05-13 18:37:00 +0000960 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000961
962 const MCExpr *Expr = getMemOff();
963 addExpr(Inst, Expr);
964 }
965
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000966 void addRegListOperands(MCInst &Inst, unsigned N) const {
967 assert(N == 1 && "Invalid number of operands!");
968
969 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000970 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000971 }
972
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000973 void addRegPairOperands(MCInst &Inst, unsigned N) const {
974 assert(N == 2 && "Invalid number of operands!");
975 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000976 Inst.addOperand(MCOperand::createReg(RegNo++));
977 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000978 }
979
Zoran Jovanovic41688672015-02-10 16:36:20 +0000980 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
981 assert(N == 2 && "Invalid number of operands!");
982 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000983 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000984 }
985
Craig Topper56c590a2014-04-29 07:58:02 +0000986 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000987 // As a special case until we sort out the definition of div/divu, pretend
988 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
989 if (isGPRAsmReg() && RegIdx.Index == 0)
990 return true;
991
992 return Kind == k_PhysRegister;
993 }
994 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000995 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000996 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +0000997 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000998 }
Daniel Sanders52da7af2015-11-06 12:11:03 +0000999 bool isConstantImmz() const {
1000 return isConstantImm() && getConstantImm() == 0;
1001 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001002 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1003 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1004 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001005 template <unsigned Bits> bool isUImm() const {
1006 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
1007 }
Craig Topper56c590a2014-04-29 07:58:02 +00001008 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001009 // Note: It's not possible to pretend that other operand kinds are tokens.
1010 // The matcher emitter checks tokens first.
1011 return Kind == k_Token;
1012 }
Craig Topper56c590a2014-04-29 07:58:02 +00001013 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001014 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001015 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001016 }
1017 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001018 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1019 && getMemBase()->isGPRAsmReg();
1020 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001021 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
1022 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
1023 getMemBase()->isGPRAsmReg();
1024 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001025 bool isMemWithGRPMM16Base() const {
1026 return isMem() && getMemBase()->isMM16AsmReg();
1027 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001028 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1029 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1030 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1031 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001032 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1033 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1034 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1035 && (getMemBase()->getGPR32Reg() == Mips::SP);
1036 }
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001037 bool isUImm5Lsl2() const {
1038 return (isImm() && isConstantImm() && isShiftedUInt<5, 2>(getConstantImm()));
1039 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001040 bool isRegList16() const {
1041 if (!isRegList())
1042 return false;
1043
1044 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001045 if (Size < 2 || Size > 5)
1046 return false;
1047
1048 unsigned R0 = RegList.List->front();
1049 unsigned R1 = RegList.List->back();
1050 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1051 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001052 return false;
1053
1054 int PrevReg = *RegList.List->begin();
1055 for (int i = 1; i < Size - 1; i++) {
1056 int Reg = (*(RegList.List))[i];
1057 if ( Reg != PrevReg + 1)
1058 return false;
1059 PrevReg = Reg;
1060 }
1061
1062 return true;
1063 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001064 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001065 bool isLSAImm() const {
1066 if (!isConstantImm())
1067 return false;
1068 int64_t Val = getConstantImm();
1069 return 1 <= Val && Val <= 4;
1070 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001071 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001072 bool isMovePRegPair() const {
1073 if (Kind != k_RegList || RegList.List->size() != 2)
1074 return false;
1075
1076 unsigned R0 = RegList.List->front();
1077 unsigned R1 = RegList.List->back();
1078
1079 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1080 (R0 == Mips::A1 && R1 == Mips::A3) ||
1081 (R0 == Mips::A2 && R1 == Mips::A3) ||
1082 (R0 == Mips::A0 && R1 == Mips::S5) ||
1083 (R0 == Mips::A0 && R1 == Mips::S6) ||
1084 (R0 == Mips::A0 && R1 == Mips::A1) ||
1085 (R0 == Mips::A0 && R1 == Mips::A2) ||
1086 (R0 == Mips::A0 && R1 == Mips::A3))
1087 return true;
1088
1089 return false;
1090 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001091
1092 StringRef getToken() const {
1093 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001094 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001095 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001096 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001097
Craig Topper56c590a2014-04-29 07:58:02 +00001098 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001099 // As a special case until we sort out the definition of div/divu, pretend
1100 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1101 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1102 RegIdx.Kind & RegKind_GPR)
1103 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001104
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 assert(Kind == k_PhysRegister && "Invalid access!");
1106 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001107 }
1108
Jack Carterb4dbc172012-09-05 23:34:03 +00001109 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001110 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001111 return Imm.Val;
1112 }
1113
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001114 int64_t getConstantImm() const {
1115 const MCExpr *Val = getImm();
1116 return static_cast<const MCConstantExpr *>(Val)->getValue();
1117 }
1118
1119 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001120 assert((Kind == k_Memory) && "Invalid access!");
1121 return Mem.Base;
1122 }
1123
1124 const MCExpr *getMemOff() const {
1125 assert((Kind == k_Memory) && "Invalid access!");
1126 return Mem.Off;
1127 }
1128
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001129 int64_t getConstantMemOff() const {
1130 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1131 }
1132
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001133 const SmallVectorImpl<unsigned> &getRegList() const {
1134 assert((Kind == k_RegList) && "Invalid access!");
1135 return *(RegList.List);
1136 }
1137
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001138 unsigned getRegPair() const {
1139 assert((Kind == k_RegPair) && "Invalid access!");
1140 return RegIdx.Index;
1141 }
1142
David Blaikie960ea3f2014-06-08 16:18:35 +00001143 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1144 MipsAsmParser &Parser) {
1145 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001146 Op->Tok.Data = Str.data();
1147 Op->Tok.Length = Str.size();
1148 Op->StartLoc = S;
1149 Op->EndLoc = S;
1150 return Op;
1151 }
1152
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001153 /// Create a numeric register (e.g. $1). The exact register remains
1154 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001155 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001156 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001157 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001158 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001159 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001160 }
1161
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001162 /// Create a register that is definitely a GPR.
1163 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001164 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001165 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001166 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001167 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001168 }
1169
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001170 /// Create a register that is definitely a FGR.
1171 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001172 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001173 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001174 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001175 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1176 }
1177
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001178 /// Create a register that is definitely a HWReg.
1179 /// This is typically only used for named registers such as $hwr_cpunum.
1180 static std::unique_ptr<MipsOperand>
1181 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1182 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1183 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1184 }
1185
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001186 /// Create a register that is definitely an FCC.
1187 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001188 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001189 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001190 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001191 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1192 }
1193
1194 /// Create a register that is definitely an ACC.
1195 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001196 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001197 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001198 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001199 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1200 }
1201
1202 /// Create a register that is definitely an MSA128.
1203 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001204 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001205 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001206 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001207 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1208 }
1209
1210 /// Create a register that is definitely an MSACtrl.
1211 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001212 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001213 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001214 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001215 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1216 }
1217
David Blaikie960ea3f2014-06-08 16:18:35 +00001218 static std::unique_ptr<MipsOperand>
1219 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1220 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001221 Op->Imm.Val = Val;
1222 Op->StartLoc = S;
1223 Op->EndLoc = E;
1224 return Op;
1225 }
1226
David Blaikie960ea3f2014-06-08 16:18:35 +00001227 static std::unique_ptr<MipsOperand>
1228 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1229 SMLoc E, MipsAsmParser &Parser) {
1230 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1231 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001232 Op->Mem.Off = Off;
1233 Op->StartLoc = S;
1234 Op->EndLoc = E;
1235 return Op;
1236 }
1237
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001238 static std::unique_ptr<MipsOperand>
1239 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1240 MipsAsmParser &Parser) {
1241 assert (Regs.size() > 0 && "Empty list not allowed");
1242
1243 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001244 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001245 Op->StartLoc = StartLoc;
1246 Op->EndLoc = EndLoc;
1247 return Op;
1248 }
1249
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001250 static std::unique_ptr<MipsOperand>
1251 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1252 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1253 Op->RegIdx.Index = RegNo;
1254 Op->StartLoc = S;
1255 Op->EndLoc = E;
1256 return Op;
1257 }
1258
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001259 bool isGPRAsmReg() const {
1260 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001261 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001262 bool isMM16AsmReg() const {
1263 if (!(isRegIdx() && RegIdx.Kind))
1264 return false;
1265 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1266 || RegIdx.Index == 16 || RegIdx.Index == 17);
1267 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001268 bool isMM16AsmRegZero() const {
1269 if (!(isRegIdx() && RegIdx.Kind))
1270 return false;
1271 return (RegIdx.Index == 0 ||
1272 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1273 RegIdx.Index == 17);
1274 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001275 bool isMM16AsmRegMoveP() const {
1276 if (!(isRegIdx() && RegIdx.Kind))
1277 return false;
1278 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1279 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1280 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001281 bool isFGRAsmReg() const {
1282 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1283 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001284 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001285 bool isHWRegsAsmReg() const {
1286 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001287 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001288 bool isCCRAsmReg() const {
1289 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001290 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001291 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001292 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1293 return false;
1294 if (!AsmParser.hasEightFccRegisters())
1295 return RegIdx.Index == 0;
1296 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001297 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001298 bool isACCAsmReg() const {
1299 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001300 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001301 bool isCOP0AsmReg() const {
1302 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1303 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001304 bool isCOP2AsmReg() const {
1305 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001306 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001307 bool isCOP3AsmReg() const {
1308 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1309 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001310 bool isMSA128AsmReg() const {
1311 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001312 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001313 bool isMSACtrlAsmReg() const {
1314 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001315 }
1316
Jack Carterb4dbc172012-09-05 23:34:03 +00001317 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001318 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001319 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001320 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001321
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001322 virtual ~MipsOperand() {
1323 switch (Kind) {
1324 case k_Immediate:
1325 break;
1326 case k_Memory:
1327 delete Mem.Base;
1328 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001329 case k_RegList:
1330 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001331 case k_PhysRegister:
1332 case k_RegisterIndex:
1333 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001334 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001335 break;
1336 }
1337 }
1338
Craig Topper56c590a2014-04-29 07:58:02 +00001339 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001340 switch (Kind) {
1341 case k_Immediate:
1342 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001343 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001344 OS << ">";
1345 break;
1346 case k_Memory:
1347 OS << "Mem<";
1348 Mem.Base->print(OS);
1349 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001350 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001351 OS << ">";
1352 break;
1353 case k_PhysRegister:
1354 OS << "PhysReg<" << PhysReg.Num << ">";
1355 break;
1356 case k_RegisterIndex:
1357 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1358 break;
1359 case k_Token:
1360 OS << Tok.Data;
1361 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001362 case k_RegList:
1363 OS << "RegList< ";
1364 for (auto Reg : (*RegList.List))
1365 OS << Reg << " ";
1366 OS << ">";
1367 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001368 case k_RegPair:
1369 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1370 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001371 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001372 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001373}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001374} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001375
Jack Carter9e65aa32013-03-22 00:05:30 +00001376namespace llvm {
1377extern const MCInstrDesc MipsInsts[];
1378}
1379static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1380 return MipsInsts[Opcode];
1381}
1382
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001383static bool hasShortDelaySlot(unsigned Opcode) {
1384 switch (Opcode) {
1385 case Mips::JALS_MM:
1386 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001387 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001388 case Mips::BGEZALS_MM:
1389 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001390 return true;
1391 default:
1392 return false;
1393 }
1394}
1395
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001396static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1397 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1398 return &SRExpr->getSymbol();
1399 }
1400
1401 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1402 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1403 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1404
1405 if (LHSSym)
1406 return LHSSym;
1407
1408 if (RHSSym)
1409 return RHSSym;
1410
1411 return nullptr;
1412 }
1413
1414 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1415 return getSingleMCSymbol(UExpr->getSubExpr());
1416
1417 return nullptr;
1418}
1419
1420static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1421 if (isa<MCSymbolRefExpr>(Expr))
1422 return 1;
1423
1424 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1425 return countMCSymbolRefExpr(BExpr->getLHS()) +
1426 countMCSymbolRefExpr(BExpr->getRHS());
1427
1428 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1429 return countMCSymbolRefExpr(UExpr->getSubExpr());
1430
1431 return 0;
1432}
1433
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001434namespace {
1435void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1436 SmallVectorImpl<MCInst> &Instructions) {
1437 MCInst tmpInst;
1438 tmpInst.setOpcode(Opcode);
1439 tmpInst.addOperand(MCOperand::createReg(Reg0));
1440 tmpInst.addOperand(Op1);
1441 tmpInst.setLoc(IDLoc);
1442 Instructions.push_back(tmpInst);
1443}
1444
1445void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1446 SmallVectorImpl<MCInst> &Instructions) {
1447 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1448}
1449
1450void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1451 SmallVectorImpl<MCInst> &Instructions) {
1452 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1453}
1454
1455void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1456 SmallVectorImpl<MCInst> &Instructions) {
1457 MCInst tmpInst;
1458 tmpInst.setOpcode(Opcode);
1459 tmpInst.addOperand(MCOperand::createImm(Imm1));
1460 tmpInst.addOperand(MCOperand::createImm(Imm2));
1461 tmpInst.setLoc(IDLoc);
1462 Instructions.push_back(tmpInst);
1463}
1464
1465void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1466 SmallVectorImpl<MCInst> &Instructions) {
1467 MCInst tmpInst;
1468 tmpInst.setOpcode(Opcode);
1469 tmpInst.addOperand(MCOperand::createReg(Reg0));
1470 tmpInst.setLoc(IDLoc);
1471 Instructions.push_back(tmpInst);
1472}
1473
1474void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1475 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1476 MCInst tmpInst;
1477 tmpInst.setOpcode(Opcode);
1478 tmpInst.addOperand(MCOperand::createReg(Reg0));
1479 tmpInst.addOperand(MCOperand::createReg(Reg1));
1480 tmpInst.addOperand(Op2);
1481 tmpInst.setLoc(IDLoc);
1482 Instructions.push_back(tmpInst);
1483}
1484
1485void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1486 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1487 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1488 Instructions);
1489}
1490
1491void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1492 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1493 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1494 Instructions);
1495}
1496
1497void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1498 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1499 if (ShiftAmount >= 32) {
1500 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1501 Instructions);
1502 return;
1503 }
1504
1505 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1506}
1507} // end anonymous namespace.
1508
Jack Carter9e65aa32013-03-22 00:05:30 +00001509bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001510 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001511 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001512 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001513
Jack Carter9e65aa32013-03-22 00:05:30 +00001514 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001515
1516 if (MCID.isBranch() || MCID.isCall()) {
1517 const unsigned Opcode = Inst.getOpcode();
1518 MCOperand Offset;
1519
1520 switch (Opcode) {
1521 default:
1522 break;
Kai Nackee0245392015-01-27 19:11:28 +00001523 case Mips::BBIT0:
1524 case Mips::BBIT032:
1525 case Mips::BBIT1:
1526 case Mips::BBIT132:
1527 assert(hasCnMips() && "instruction only valid for octeon cpus");
1528 // Fall through
1529
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001530 case Mips::BEQ:
1531 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001532 case Mips::BEQ_MM:
1533 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001534 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001535 Offset = Inst.getOperand(2);
1536 if (!Offset.isImm())
1537 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001538 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001539 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001540 if (OffsetToAlignment(Offset.getImm(),
1541 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001542 return Error(IDLoc, "branch to misaligned address");
1543 break;
1544 case Mips::BGEZ:
1545 case Mips::BGTZ:
1546 case Mips::BLEZ:
1547 case Mips::BLTZ:
1548 case Mips::BGEZAL:
1549 case Mips::BLTZAL:
1550 case Mips::BC1F:
1551 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001552 case Mips::BGEZ_MM:
1553 case Mips::BGTZ_MM:
1554 case Mips::BLEZ_MM:
1555 case Mips::BLTZ_MM:
1556 case Mips::BGEZAL_MM:
1557 case Mips::BLTZAL_MM:
1558 case Mips::BC1F_MM:
1559 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001560 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001561 Offset = Inst.getOperand(1);
1562 if (!Offset.isImm())
1563 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001564 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001565 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001566 if (OffsetToAlignment(Offset.getImm(),
1567 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001568 return Error(IDLoc, "branch to misaligned address");
1569 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001570 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001571 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001572 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001573 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001574 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1575 Offset = Inst.getOperand(1);
1576 if (!Offset.isImm())
1577 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001578 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001579 return Error(IDLoc, "branch target out of range");
1580 if (OffsetToAlignment(Offset.getImm(), 2LL))
1581 return Error(IDLoc, "branch to misaligned address");
1582 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001583 }
1584 }
1585
Daniel Sandersa84989a2014-06-16 13:25:35 +00001586 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1587 // We still accept it but it is a normal nop.
1588 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1589 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1590 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1591 "nop instruction");
1592 }
1593
Kai Nackee0245392015-01-27 19:11:28 +00001594 if (hasCnMips()) {
1595 const unsigned Opcode = Inst.getOpcode();
1596 MCOperand Opnd;
1597 int Imm;
1598
1599 switch (Opcode) {
1600 default:
1601 break;
1602
1603 case Mips::BBIT0:
1604 case Mips::BBIT032:
1605 case Mips::BBIT1:
1606 case Mips::BBIT132:
1607 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1608 // The offset is handled above
1609 Opnd = Inst.getOperand(1);
1610 if (!Opnd.isImm())
1611 return Error(IDLoc, "expected immediate operand kind");
1612 Imm = Opnd.getImm();
1613 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1614 Opcode == Mips::BBIT1 ? 63 : 31))
1615 return Error(IDLoc, "immediate operand value out of range");
1616 if (Imm > 31) {
1617 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1618 : Mips::BBIT132);
1619 Inst.getOperand(1).setImm(Imm - 32);
1620 }
1621 break;
1622
1623 case Mips::CINS:
1624 case Mips::CINS32:
1625 case Mips::EXTS:
1626 case Mips::EXTS32:
1627 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1628 // Check length
1629 Opnd = Inst.getOperand(3);
1630 if (!Opnd.isImm())
1631 return Error(IDLoc, "expected immediate operand kind");
1632 Imm = Opnd.getImm();
1633 if (Imm < 0 || Imm > 31)
1634 return Error(IDLoc, "immediate operand value out of range");
1635 // Check position
1636 Opnd = Inst.getOperand(2);
1637 if (!Opnd.isImm())
1638 return Error(IDLoc, "expected immediate operand kind");
1639 Imm = Opnd.getImm();
1640 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1641 Opcode == Mips::EXTS ? 63 : 31))
1642 return Error(IDLoc, "immediate operand value out of range");
1643 if (Imm > 31) {
1644 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1645 Inst.getOperand(2).setImm(Imm - 32);
1646 }
1647 break;
1648
1649 case Mips::SEQi:
1650 case Mips::SNEi:
1651 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1652 Opnd = Inst.getOperand(2);
1653 if (!Opnd.isImm())
1654 return Error(IDLoc, "expected immediate operand kind");
1655 Imm = Opnd.getImm();
1656 if (!isInt<10>(Imm))
1657 return Error(IDLoc, "immediate operand value out of range");
1658 break;
1659 }
1660 }
1661
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001662 // This expansion is not in a function called by tryExpandInstruction()
1663 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001664 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1665 inPicMode()) {
1666 warnIfNoMacro(IDLoc);
1667
1668 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1669
1670 // We can do this expansion if there's only 1 symbol in the argument
1671 // expression.
1672 if (countMCSymbolRefExpr(JalExpr) > 1)
1673 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1674
1675 // FIXME: This is checking the expression can be handled by the later stages
1676 // of the assembler. We ought to leave it to those later stages but
1677 // we can't do that until we stop evaluateRelocExpr() rewriting the
1678 // expressions into non-equivalent forms.
1679 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1680
1681 // FIXME: Add support for label+offset operands (currently causes an error).
1682 // FIXME: Add support for forward-declared local symbols.
1683 // FIXME: Add expansion for when the LargeGOT option is enabled.
1684 if (JalSym->isInSection() || JalSym->isTemporary()) {
1685 if (isABI_O32()) {
1686 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001687 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001688 // R_(MICRO)MIPS_GOT16 label
1689 // addiu $25, $25, 0
1690 // R_(MICRO)MIPS_LO16 label
1691 // jalr $25
1692 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1693 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1694
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001695 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1696 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1697 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1698 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001699 } else if (isABI_N32() || isABI_N64()) {
1700 // If it's a local symbol and the N32/N64 ABIs are being used,
1701 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001702 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001703 // R_(MICRO)MIPS_GOT_DISP label
1704 // jalr $25
1705 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1706
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001707 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1708 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001709 }
1710 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001711 // If it's an external/weak symbol, we expand to:
1712 // lw/ld $25, 0($gp)
1713 // R_(MICRO)MIPS_CALL16 label
1714 // jalr $25
1715 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001716
Daniel Sandersb7002032015-11-20 13:16:35 +00001717 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1718 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001719 }
1720
1721 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001722 if (IsCpRestoreSet && inMicroMipsMode())
1723 JalrInst.setOpcode(Mips::JALRS_MM);
1724 else
1725 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001726 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1727 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1728
1729 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1730 // This relocation is supposed to be an optimization hint for the linker
1731 // and is not necessary for correctness.
1732
1733 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001734 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001735 }
1736
Jack Carter9e65aa32013-03-22 00:05:30 +00001737 if (MCID.mayLoad() || MCID.mayStore()) {
1738 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001739 // reference or immediate we may have to expand instructions.
1740 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001741 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001742 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1743 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001744 MCOperand &Op = Inst.getOperand(i);
1745 if (Op.isImm()) {
1746 int MemOffset = Op.getImm();
1747 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001748 // Offset can't exceed 16bit value.
1749 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001750 return false;
1751 }
1752 } else if (Op.isExpr()) {
1753 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001754 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001755 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001756 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001757 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001758 // Expand symbol.
1759 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001760 return false;
1761 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001762 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001763 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001764 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001765 }
1766 }
1767 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001768 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001769 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001770
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001771 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001772 if (MCID.mayLoad()) {
1773 // Try to create 16-bit GP relative load instruction.
1774 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1775 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1776 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1777 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1778 MCOperand &Op = Inst.getOperand(i);
1779 if (Op.isImm()) {
1780 int MemOffset = Op.getImm();
1781 MCOperand &DstReg = Inst.getOperand(0);
1782 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001783 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001784 getContext().getRegisterInfo()->getRegClass(
1785 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001786 (BaseReg.getReg() == Mips::GP ||
1787 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001788
1789 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1790 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001791 return false;
1792 }
1793 }
1794 }
1795 } // for
1796 } // if load
1797
1798 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1799
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001800 MCOperand Opnd;
1801 int Imm;
1802
1803 switch (Inst.getOpcode()) {
1804 default:
1805 break;
1806 case Mips::ADDIUS5_MM:
1807 Opnd = Inst.getOperand(2);
1808 if (!Opnd.isImm())
1809 return Error(IDLoc, "expected immediate operand kind");
1810 Imm = Opnd.getImm();
1811 if (Imm < -8 || Imm > 7)
1812 return Error(IDLoc, "immediate operand value out of range");
1813 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001814 case Mips::ADDIUSP_MM:
1815 Opnd = Inst.getOperand(0);
1816 if (!Opnd.isImm())
1817 return Error(IDLoc, "expected immediate operand kind");
1818 Imm = Opnd.getImm();
1819 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1820 Imm % 4 != 0)
1821 return Error(IDLoc, "immediate operand value out of range");
1822 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001823 case Mips::SLL16_MM:
1824 case Mips::SRL16_MM:
1825 Opnd = Inst.getOperand(2);
1826 if (!Opnd.isImm())
1827 return Error(IDLoc, "expected immediate operand kind");
1828 Imm = Opnd.getImm();
1829 if (Imm < 1 || Imm > 8)
1830 return Error(IDLoc, "immediate operand value out of range");
1831 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001832 case Mips::LI16_MM:
1833 Opnd = Inst.getOperand(1);
1834 if (!Opnd.isImm())
1835 return Error(IDLoc, "expected immediate operand kind");
1836 Imm = Opnd.getImm();
1837 if (Imm < -1 || Imm > 126)
1838 return Error(IDLoc, "immediate operand value out of range");
1839 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001840 case Mips::ADDIUR2_MM:
1841 Opnd = Inst.getOperand(2);
1842 if (!Opnd.isImm())
1843 return Error(IDLoc, "expected immediate operand kind");
1844 Imm = Opnd.getImm();
1845 if (!(Imm == 1 || Imm == -1 ||
1846 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1847 return Error(IDLoc, "immediate operand value out of range");
1848 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001849 case Mips::ADDIUR1SP_MM:
1850 Opnd = Inst.getOperand(1);
1851 if (!Opnd.isImm())
1852 return Error(IDLoc, "expected immediate operand kind");
1853 Imm = Opnd.getImm();
1854 if (OffsetToAlignment(Imm, 4LL))
1855 return Error(IDLoc, "misaligned immediate operand value");
1856 if (Imm < 0 || Imm > 255)
1857 return Error(IDLoc, "immediate operand value out of range");
1858 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001859 case Mips::ANDI16_MM:
1860 Opnd = Inst.getOperand(2);
1861 if (!Opnd.isImm())
1862 return Error(IDLoc, "expected immediate operand kind");
1863 Imm = Opnd.getImm();
1864 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1865 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1866 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1867 return Error(IDLoc, "immediate operand value out of range");
1868 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001869 case Mips::LBU16_MM:
1870 Opnd = Inst.getOperand(2);
1871 if (!Opnd.isImm())
1872 return Error(IDLoc, "expected immediate operand kind");
1873 Imm = Opnd.getImm();
1874 if (Imm < -1 || Imm > 14)
1875 return Error(IDLoc, "immediate operand value out of range");
1876 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001877 case Mips::TEQ_MM:
1878 case Mips::TGE_MM:
1879 case Mips::TGEU_MM:
1880 case Mips::TLT_MM:
1881 case Mips::TLTU_MM:
1882 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001883 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001884 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001885 Opnd = Inst.getOperand(2);
1886 if (!Opnd.isImm())
1887 return Error(IDLoc, "expected immediate operand kind");
1888 Imm = Opnd.getImm();
1889 if (Imm < 0 || Imm > 15)
1890 return Error(IDLoc, "immediate operand value out of range");
1891 break;
1892 case Mips::LHU16_MM:
1893 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001894 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001895 Opnd = Inst.getOperand(2);
1896 if (!Opnd.isImm())
1897 return Error(IDLoc, "expected immediate operand kind");
1898 Imm = Opnd.getImm();
1899 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1900 return Error(IDLoc, "immediate operand value out of range");
1901 break;
1902 case Mips::LW16_MM:
1903 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001904 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001905 Opnd = Inst.getOperand(2);
1906 if (!Opnd.isImm())
1907 return Error(IDLoc, "expected immediate operand kind");
1908 Imm = Opnd.getImm();
1909 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1910 return Error(IDLoc, "immediate operand value out of range");
1911 break;
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001912 case Mips::PREFX_MM:
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001913 case Mips::CACHE:
1914 case Mips::PREF:
1915 Opnd = Inst.getOperand(2);
1916 if (!Opnd.isImm())
1917 return Error(IDLoc, "expected immediate operand kind");
1918 Imm = Opnd.getImm();
1919 if (!isUInt<5>(Imm))
1920 return Error(IDLoc, "immediate operand value out of range");
1921 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001922 case Mips::ADDIUPC_MM:
1923 MCOperand Opnd = Inst.getOperand(1);
1924 if (!Opnd.isImm())
1925 return Error(IDLoc, "expected immediate operand kind");
1926 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001927 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001928 return Error(IDLoc, "immediate operand value out of range");
1929 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001930 }
1931 }
1932
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001933 MacroExpanderResultTy ExpandResult =
1934 tryExpandInstruction(Inst, IDLoc, Instructions);
1935 switch (ExpandResult) {
1936 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001937 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001938 break;
1939 case MER_Success:
1940 break;
1941 case MER_Fail:
1942 return true;
1943 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001944
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001945 // If this instruction has a delay slot and .set reorder is active,
1946 // emit a NOP after it.
1947 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1948 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1949
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001950 if ((Inst.getOpcode() == Mips::JalOneReg ||
1951 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1952 isPicAndNotNxxAbi()) {
1953 if (IsCpRestoreSet) {
1954 // We need a NOP between the JALR and the LW:
1955 // If .set reorder has been used, we've already emitted a NOP.
1956 // If .set noreorder has been used, we need to emit a NOP at this point.
1957 if (!AssemblerOptions.back()->isReorder())
1958 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1959
1960 // Load the $gp from the stack.
1961 SmallVector<MCInst, 3> LoadInsts;
1962 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1963 IDLoc, LoadInsts);
1964
1965 for (const MCInst &Inst : LoadInsts)
1966 Instructions.push_back(Inst);
1967
1968 } else
1969 Warning(IDLoc, "no .cprestore used in PIC mode");
1970 }
1971
Jack Carter9e65aa32013-03-22 00:05:30 +00001972 return false;
1973}
1974
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001975MipsAsmParser::MacroExpanderResultTy
1976MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1977 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001978 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001979 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001980 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001981 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001982 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1983 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001984 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001985 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1986 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001987 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001988 case Mips::LoadAddrImm64:
1989 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1990 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1991 "expected immediate operand kind");
1992
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001993 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1994 Inst.getOperand(1),
1995 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1996 Instructions)
1997 ? MER_Fail
1998 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001999 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002000 case Mips::LoadAddrReg64:
2001 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2002 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2003 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2004 "expected immediate operand kind");
2005
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002006 return expandLoadAddress(Inst.getOperand(0).getReg(),
2007 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2008 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
2009 Instructions)
2010 ? MER_Fail
2011 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002012 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002013 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002014 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
2015 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002016 case Mips::SWM_MM:
2017 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002018 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
2019 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002020 case Mips::JalOneReg:
2021 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002022 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
2023 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002024 case Mips::BneImm:
2025 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002026 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002027 case Mips::BLT:
2028 case Mips::BLE:
2029 case Mips::BGE:
2030 case Mips::BGT:
2031 case Mips::BLTU:
2032 case Mips::BLEU:
2033 case Mips::BGEU:
2034 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002035 case Mips::BLTL:
2036 case Mips::BLEL:
2037 case Mips::BGEL:
2038 case Mips::BGTL:
2039 case Mips::BLTUL:
2040 case Mips::BLEUL:
2041 case Mips::BGEUL:
2042 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002043 case Mips::BLTImmMacro:
2044 case Mips::BLEImmMacro:
2045 case Mips::BGEImmMacro:
2046 case Mips::BGTImmMacro:
2047 case Mips::BLTUImmMacro:
2048 case Mips::BLEUImmMacro:
2049 case Mips::BGEUImmMacro:
2050 case Mips::BGTUImmMacro:
2051 case Mips::BLTLImmMacro:
2052 case Mips::BLELImmMacro:
2053 case Mips::BGELImmMacro:
2054 case Mips::BGTLImmMacro:
2055 case Mips::BLTULImmMacro:
2056 case Mips::BLEULImmMacro:
2057 case Mips::BGEULImmMacro:
2058 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002059 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2060 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002061 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002062 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2063 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002064 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002065 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2066 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002067 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002068 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2069 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002070 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002071 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2072 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002073 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002074 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002075 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002076 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002077 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002078 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2079 case Mips::NORImm:
2080 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2081 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002082 case Mips::ADDi:
2083 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002084 case Mips::SLTi:
2085 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002086 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2087 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2088 int64_t ImmValue = Inst.getOperand(2).getImm();
2089 if (isInt<16>(ImmValue))
2090 return MER_NotAMacro;
2091 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2092 : MER_Success;
2093 }
2094 return MER_NotAMacro;
2095 case Mips::ANDi:
2096 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002097 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002098 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2099 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2100 int64_t ImmValue = Inst.getOperand(2).getImm();
2101 if (isUInt<16>(ImmValue))
2102 return MER_NotAMacro;
2103 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2104 : MER_Success;
2105 }
2106 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002107 case Mips::ROL:
2108 case Mips::ROR:
2109 return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail
2110 : MER_Success;
2111 case Mips::ROLImm:
2112 case Mips::RORImm:
2113 return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2114 : MER_Success;
2115 case Mips::DROL:
2116 case Mips::DROR:
2117 return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail
2118 : MER_Success;
2119 case Mips::DROLImm:
2120 case Mips::DRORImm:
2121 return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2122 : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002123 }
Jack Carter30a59822012-10-04 04:03:53 +00002124}
Jack Carter92995f12012-10-06 00:53:28 +00002125
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002126bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2127 SmallVectorImpl<MCInst> &Instructions) {
2128 // Create a JALR instruction which is going to replace the pseudo-JAL.
2129 MCInst JalrInst;
2130 JalrInst.setLoc(IDLoc);
2131 const MCOperand FirstRegOp = Inst.getOperand(0);
2132 const unsigned Opcode = Inst.getOpcode();
2133
2134 if (Opcode == Mips::JalOneReg) {
2135 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002136 if (IsCpRestoreSet && inMicroMipsMode()) {
2137 JalrInst.setOpcode(Mips::JALRS16_MM);
2138 JalrInst.addOperand(FirstRegOp);
2139 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002140 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002141 JalrInst.addOperand(FirstRegOp);
2142 } else {
2143 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002144 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002145 JalrInst.addOperand(FirstRegOp);
2146 }
2147 } else if (Opcode == Mips::JalTwoReg) {
2148 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002149 if (IsCpRestoreSet && inMicroMipsMode())
2150 JalrInst.setOpcode(Mips::JALRS_MM);
2151 else
2152 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002153 JalrInst.addOperand(FirstRegOp);
2154 const MCOperand SecondRegOp = Inst.getOperand(1);
2155 JalrInst.addOperand(SecondRegOp);
2156 }
2157 Instructions.push_back(JalrInst);
2158
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002159 // If .set reorder is active and branch instruction has a delay slot,
2160 // emit a NOP after it.
2161 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2162 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002163 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002164 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002165
2166 return false;
2167}
2168
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002169/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002170template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002171 unsigned BitNum = findFirstSet(x);
2172
2173 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2174}
2175
2176/// Load (or add) an immediate into a register.
2177///
2178/// @param ImmValue The immediate to load.
2179/// @param DstReg The register that will hold the immediate.
2180/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2181/// for a simple initialization.
2182/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2183/// @param IsAddress True if the immediate represents an address. False if it
2184/// is an integer.
2185/// @param IDLoc Location of the immediate in the source file.
2186/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002187bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002188 unsigned SrcReg, bool Is32BitImm,
2189 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002190 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002191 if (!Is32BitImm && !isGP64bit()) {
2192 Error(IDLoc, "instruction requires a 64-bit architecture");
2193 return true;
2194 }
2195
Daniel Sanders03f9c012015-07-14 12:24:22 +00002196 if (Is32BitImm) {
2197 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2198 // Sign extend up to 64-bit so that the predicates match the hardware
2199 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2200 // true.
2201 ImmValue = SignExtend64<32>(ImmValue);
2202 } else {
2203 Error(IDLoc, "instruction requires a 32-bit immediate");
2204 return true;
2205 }
2206 }
2207
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002208 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2209 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2210
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002211 bool UseSrcReg = false;
2212 if (SrcReg != Mips::NoRegister)
2213 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002214
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002215 unsigned TmpReg = DstReg;
2216 if (UseSrcReg && (DstReg == SrcReg)) {
2217 // 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.
2380 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2381 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
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002389 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2390 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002391}
2392
Toma Tabacuf712ede2015-06-17 14:31:51 +00002393bool MipsAsmParser::loadAndAddSymbolAddress(
2394 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2395 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002396 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002397
Daniel Sandersd5a89412015-10-05 13:19:29 +00002398 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2399 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2400 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2401 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2402 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002403
Toma Tabacufb9d1252015-06-22 12:08:39 +00002404 bool UseSrcReg = SrcReg != Mips::NoRegister;
2405
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002406 // This is the 64-bit symbol address expansion.
2407 if (ABI.ArePtrs64bit() && isGP64bit()) {
2408 // We always need AT for the 64-bit expansion.
2409 // If it is not available we exit.
2410 unsigned ATReg = getATReg(IDLoc);
2411 if (!ATReg)
2412 return true;
2413
Daniel Sandersd5a89412015-10-05 13:19:29 +00002414 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2415 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2416 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2417 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002418
2419 if (UseSrcReg && (DstReg == SrcReg)) {
2420 // If $rs is the same as $rd:
2421 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2422 // daddiu $at, $at, %higher(sym)
2423 // dsll $at, $at, 16
2424 // daddiu $at, $at, %hi(sym)
2425 // dsll $at, $at, 16
2426 // daddiu $at, $at, %lo(sym)
2427 // daddu $rd, $at, $rd
2428 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2429 Instructions);
2430 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2431 IDLoc, Instructions);
2432 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2433 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2434 Instructions);
2435 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2436 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2437 Instructions);
2438 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2439
2440 return false;
2441 }
2442
2443 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2444 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2445 // lui $at, %hi(sym)
2446 // daddiu $rd, $rd, %higher(sym)
2447 // daddiu $at, $at, %lo(sym)
2448 // dsll32 $rd, $rd, 0
2449 // daddu $rd, $rd, $at
2450 // (daddu $rd, $rd, $rs)
2451 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2452 Instructions);
2453 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2454 Instructions);
2455 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2456 IDLoc, Instructions);
2457 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2458 Instructions);
2459 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2460 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2461 if (UseSrcReg)
2462 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2463
2464 return false;
2465 }
2466
2467 // And now, the 32-bit symbol address expansion:
2468 // If $rs is the same as $rd:
2469 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2470 // ori $at, $at, %lo(sym)
2471 // addu $rd, $at, $rd
2472 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2473 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2474 // ori $rd, $rd, %lo(sym)
2475 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002476 unsigned TmpReg = DstReg;
2477 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002478 // If $rs is the same as $rd, we need to use AT.
2479 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002480 unsigned ATReg = getATReg(IDLoc);
2481 if (!ATReg)
2482 return true;
2483 TmpReg = ATReg;
2484 }
2485
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002486 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2487 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2488 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002489
Toma Tabacufb9d1252015-06-22 12:08:39 +00002490 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002491 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2492 else
2493 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002494
Toma Tabacu674825c2015-06-16 12:16:24 +00002495 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002496}
2497
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002498bool MipsAsmParser::expandUncondBranchMMPseudo(
2499 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002500 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2501 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002502
2503 MCOperand Offset = Inst.getOperand(0);
2504 if (Offset.isExpr()) {
2505 Inst.clear();
2506 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002507 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2508 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2509 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002510 } else {
2511 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002512 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002513 // If offset fits into 11 bits then this instruction becomes microMIPS
2514 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002515 if (inMicroMipsMode())
2516 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002517 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002518 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002519 Error(IDLoc, "branch target out of range");
2520 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2521 Error(IDLoc, "branch to misaligned address");
2522 Inst.clear();
2523 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002524 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2525 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2526 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002527 }
2528 }
2529 Instructions.push_back(Inst);
2530
Zoran Jovanovicada70912015-09-07 11:56:37 +00002531 // If .set reorder is active and branch instruction has a delay slot,
2532 // emit a NOP after it.
2533 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2534 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002535 createNop(true, IDLoc, Instructions);
2536
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002537 return false;
2538}
2539
Toma Tabacue1e460d2015-06-11 10:36:10 +00002540bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2541 SmallVectorImpl<MCInst> &Instructions) {
2542 const MCOperand &DstRegOp = Inst.getOperand(0);
2543 assert(DstRegOp.isReg() && "expected register operand kind");
2544
2545 const MCOperand &ImmOp = Inst.getOperand(1);
2546 assert(ImmOp.isImm() && "expected immediate operand kind");
2547
2548 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2549 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2550
2551 unsigned OpCode = 0;
2552 switch(Inst.getOpcode()) {
2553 case Mips::BneImm:
2554 OpCode = Mips::BNE;
2555 break;
2556 case Mips::BeqImm:
2557 OpCode = Mips::BEQ;
2558 break;
2559 default:
2560 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2561 break;
2562 }
2563
2564 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002565 if (ImmValue == 0)
2566 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2567 Instructions);
2568 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002569 warnIfNoMacro(IDLoc);
2570
2571 unsigned ATReg = getATReg(IDLoc);
2572 if (!ATReg)
2573 return true;
2574
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002575 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2576 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002577 return true;
2578
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002579 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002580 }
2581 return false;
2582}
2583
Jack Carter9e65aa32013-03-22 00:05:30 +00002584void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002585 SmallVectorImpl<MCInst> &Instructions,
2586 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002587 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002588 const MCExpr *ExprOffset;
2589 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002590 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002591 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2592 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002593 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002594 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2595 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002596 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002597 if (isImmOpnd) {
2598 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2599 ImmOffset = Inst.getOperand(2).getImm();
2600 LoOffset = ImmOffset & 0x0000ffff;
2601 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002602 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002603 if (LoOffset & 0x8000)
2604 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002605 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002606 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002607 // These are some of the types of expansions we perform here:
2608 // 1) lw $8, sym => lui $8, %hi(sym)
2609 // lw $8, %lo(sym)($8)
2610 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2611 // add $8, $8, $9
2612 // lw $8, %lo(offset)($9)
2613 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2614 // add $at, $at, $8
2615 // lw $8, %lo(offset)($at)
2616 // 4) sw $8, sym => lui $at, %hi(sym)
2617 // sw $8, %lo(sym)($at)
2618 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2619 // add $at, $at, $8
2620 // sw $8, %lo(offset)($at)
2621 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2622 // ldc1 $f0, %lo(sym)($at)
2623 //
2624 // For load instructions we can use the destination register as a temporary
2625 // if base and dst are different (examples 1 and 2) and if the base register
2626 // is general purpose otherwise we must use $at (example 6) and error if it's
2627 // not available. For stores we must use $at (examples 4 and 5) because we
2628 // must not clobber the source register setting up the offset.
2629 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2630 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2631 unsigned RegClassIDOp0 =
2632 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2633 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2634 (RegClassIDOp0 == Mips::GPR64RegClassID);
2635 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002636 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002637 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002638 // At this point we need AT to perform the expansions and we exit if it is
2639 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002640 TmpRegNum = getATReg(IDLoc);
2641 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002642 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002643 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002644
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002645 emitRX(Mips::LUi, TmpRegNum,
2646 isImmOpnd ? MCOperand::createImm(HiOffset)
2647 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2648 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002649 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002650 if (BaseRegNum != Mips::ZERO)
2651 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002652 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002653 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002654 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2655 isImmOpnd
2656 ? MCOperand::createImm(LoOffset)
2657 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2658 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002659}
2660
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002661bool
2662MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2663 SmallVectorImpl<MCInst> &Instructions) {
2664 unsigned OpNum = Inst.getNumOperands();
2665 unsigned Opcode = Inst.getOpcode();
2666 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2667
2668 assert (Inst.getOperand(OpNum - 1).isImm() &&
2669 Inst.getOperand(OpNum - 2).isReg() &&
2670 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2671
2672 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2673 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002674 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2675 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2676 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2677 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002678 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002679 if (inMicroMipsMode() && hasMips32r6())
2680 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2681 else
2682 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2683 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002684
2685 Inst.setOpcode(NewOpcode);
2686 Instructions.push_back(Inst);
2687 return false;
2688}
2689
Toma Tabacu1a108322015-06-17 13:20:24 +00002690bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2691 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002692 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002693 unsigned PseudoOpcode = Inst.getOpcode();
2694 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002695 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002696 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2697
2698 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002699 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002700
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002701 unsigned TrgReg;
2702 if (TrgOp.isReg())
2703 TrgReg = TrgOp.getReg();
2704 else if (TrgOp.isImm()) {
2705 warnIfNoMacro(IDLoc);
2706 EmittedNoMacroWarning = true;
2707
2708 TrgReg = getATReg(IDLoc);
2709 if (!TrgReg)
2710 return true;
2711
2712 switch(PseudoOpcode) {
2713 default:
2714 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2715 case Mips::BLTImmMacro:
2716 PseudoOpcode = Mips::BLT;
2717 break;
2718 case Mips::BLEImmMacro:
2719 PseudoOpcode = Mips::BLE;
2720 break;
2721 case Mips::BGEImmMacro:
2722 PseudoOpcode = Mips::BGE;
2723 break;
2724 case Mips::BGTImmMacro:
2725 PseudoOpcode = Mips::BGT;
2726 break;
2727 case Mips::BLTUImmMacro:
2728 PseudoOpcode = Mips::BLTU;
2729 break;
2730 case Mips::BLEUImmMacro:
2731 PseudoOpcode = Mips::BLEU;
2732 break;
2733 case Mips::BGEUImmMacro:
2734 PseudoOpcode = Mips::BGEU;
2735 break;
2736 case Mips::BGTUImmMacro:
2737 PseudoOpcode = Mips::BGTU;
2738 break;
2739 case Mips::BLTLImmMacro:
2740 PseudoOpcode = Mips::BLTL;
2741 break;
2742 case Mips::BLELImmMacro:
2743 PseudoOpcode = Mips::BLEL;
2744 break;
2745 case Mips::BGELImmMacro:
2746 PseudoOpcode = Mips::BGEL;
2747 break;
2748 case Mips::BGTLImmMacro:
2749 PseudoOpcode = Mips::BGTL;
2750 break;
2751 case Mips::BLTULImmMacro:
2752 PseudoOpcode = Mips::BLTUL;
2753 break;
2754 case Mips::BLEULImmMacro:
2755 PseudoOpcode = Mips::BLEUL;
2756 break;
2757 case Mips::BGEULImmMacro:
2758 PseudoOpcode = Mips::BGEUL;
2759 break;
2760 case Mips::BGTULImmMacro:
2761 PseudoOpcode = Mips::BGTUL;
2762 break;
2763 }
2764
2765 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2766 false, IDLoc, Instructions))
2767 return true;
2768 }
2769
Toma Tabacu1a108322015-06-17 13:20:24 +00002770 switch (PseudoOpcode) {
2771 case Mips::BLT:
2772 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002773 case Mips::BLTL:
2774 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002775 AcceptsEquality = false;
2776 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002777 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2778 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002779 ZeroSrcOpcode = Mips::BGTZ;
2780 ZeroTrgOpcode = Mips::BLTZ;
2781 break;
2782 case Mips::BLE:
2783 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002784 case Mips::BLEL:
2785 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002786 AcceptsEquality = true;
2787 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002788 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2789 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002790 ZeroSrcOpcode = Mips::BGEZ;
2791 ZeroTrgOpcode = Mips::BLEZ;
2792 break;
2793 case Mips::BGE:
2794 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002795 case Mips::BGEL:
2796 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002797 AcceptsEquality = true;
2798 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002799 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2800 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002801 ZeroSrcOpcode = Mips::BLEZ;
2802 ZeroTrgOpcode = Mips::BGEZ;
2803 break;
2804 case Mips::BGT:
2805 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002806 case Mips::BGTL:
2807 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002808 AcceptsEquality = false;
2809 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002810 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2811 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002812 ZeroSrcOpcode = Mips::BLTZ;
2813 ZeroTrgOpcode = Mips::BGTZ;
2814 break;
2815 default:
2816 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2817 }
2818
Toma Tabacu1a108322015-06-17 13:20:24 +00002819 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2820 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2821 if (IsSrcRegZero && IsTrgRegZero) {
2822 // FIXME: All of these Opcode-specific if's are needed for compatibility
2823 // with GAS' behaviour. However, they may not generate the most efficient
2824 // code in some circumstances.
2825 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002826 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2827 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002828 return false;
2829 }
2830 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002831 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2832 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002833 Warning(IDLoc, "branch is always taken");
2834 return false;
2835 }
2836 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002837 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2838 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002839 Warning(IDLoc, "branch is always taken");
2840 return false;
2841 }
2842 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002843 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2844 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002845 return false;
2846 }
2847 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002848 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2849 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002850 return false;
2851 }
2852 if (AcceptsEquality) {
2853 // If both registers are $0 and the pseudo-branch accepts equality, it
2854 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002855 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2856 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002857 Warning(IDLoc, "branch is always taken");
2858 return false;
2859 }
2860 // If both registers are $0 and the pseudo-branch does not accept
2861 // equality, it will never be taken, so we don't have to emit anything.
2862 return false;
2863 }
2864 if (IsSrcRegZero || IsTrgRegZero) {
2865 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2866 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2867 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2868 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2869 // the pseudo-branch will never be taken, so we don't emit anything.
2870 // This only applies to unsigned pseudo-branches.
2871 return false;
2872 }
2873 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2874 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2875 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2876 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2877 // the pseudo-branch will always be taken, so we emit an unconditional
2878 // branch.
2879 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002880 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2881 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002882 Warning(IDLoc, "branch is always taken");
2883 return false;
2884 }
2885 if (IsUnsigned) {
2886 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2887 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2888 // the pseudo-branch will be taken only when the non-zero register is
2889 // different from 0, so we emit a BNEZ.
2890 //
2891 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2892 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2893 // the pseudo-branch will be taken only when the non-zero register is
2894 // equal to 0, so we emit a BEQZ.
2895 //
2896 // Because only BLEU and BGEU branch on equality, we can use the
2897 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002898 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2899 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2900 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002901 return false;
2902 }
2903 // If we have a signed pseudo-branch and one of the registers is $0,
2904 // we can use an appropriate compare-to-zero branch. We select which one
2905 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002906 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2907 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2908 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002909 return false;
2910 }
2911
2912 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2913 // expansions. If it is not available, we return.
2914 unsigned ATRegNum = getATReg(IDLoc);
2915 if (!ATRegNum)
2916 return true;
2917
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002918 if (!EmittedNoMacroWarning)
2919 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002920
2921 // SLT fits well with 2 of our 4 pseudo-branches:
2922 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2923 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2924 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2925 // This is accomplished by using a BNEZ with the result of the SLT.
2926 //
2927 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2928 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2929 // Because only BGE and BLE branch on equality, we can use the
2930 // AcceptsEquality variable to decide when to emit the BEQZ.
2931 // Note that the order of the SLT arguments doesn't change between
2932 // opposites.
2933 //
2934 // The same applies to the unsigned variants, except that SLTu is used
2935 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002936 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2937 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2938 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002939
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002940 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2941 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2942 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2943 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002944 return false;
2945}
2946
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002947bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2948 SmallVectorImpl<MCInst> &Instructions,
2949 const bool IsMips64, const bool Signed) {
2950 if (hasMips32r6()) {
2951 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2952 return false;
2953 }
2954
2955 warnIfNoMacro(IDLoc);
2956
2957 const MCOperand &RsRegOp = Inst.getOperand(0);
2958 assert(RsRegOp.isReg() && "expected register operand kind");
2959 unsigned RsReg = RsRegOp.getReg();
2960
2961 const MCOperand &RtRegOp = Inst.getOperand(1);
2962 assert(RtRegOp.isReg() && "expected register operand kind");
2963 unsigned RtReg = RtRegOp.getReg();
2964 unsigned DivOp;
2965 unsigned ZeroReg;
2966
2967 if (IsMips64) {
2968 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2969 ZeroReg = Mips::ZERO_64;
2970 } else {
2971 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2972 ZeroReg = Mips::ZERO;
2973 }
2974
2975 bool UseTraps = useTraps();
2976
2977 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2978 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2979 Warning(IDLoc, "dividing zero by zero");
2980 if (IsMips64) {
2981 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2982 if (UseTraps) {
2983 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2984 return false;
2985 }
2986
2987 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2988 return false;
2989 }
2990 } else {
2991 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2992 return false;
2993 }
2994 }
2995
2996 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2997 Warning(IDLoc, "division by zero");
2998 if (Signed) {
2999 if (UseTraps) {
3000 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3001 return false;
3002 }
3003
3004 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3005 return false;
3006 }
3007 }
3008
3009 // FIXME: The values for these two BranchTarget variables may be different in
3010 // micromips. These magic numbers need to be removed.
3011 unsigned BranchTargetNoTraps;
3012 unsigned BranchTarget;
3013
3014 if (UseTraps) {
3015 BranchTarget = IsMips64 ? 12 : 8;
3016 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3017 } else {
3018 BranchTarget = IsMips64 ? 20 : 16;
3019 BranchTargetNoTraps = 8;
3020 // Branch to the li instruction.
3021 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
3022 Instructions);
3023 }
3024
3025 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3026
3027 if (!UseTraps)
3028 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3029
3030 if (!Signed) {
3031 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3032 return false;
3033 }
3034
3035 unsigned ATReg = getATReg(IDLoc);
3036 if (!ATReg)
3037 return true;
3038
3039 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
3040 if (IsMips64) {
3041 // Branch to the mflo instruction.
3042 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3043 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
3044 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
3045 } else {
3046 // Branch to the mflo instruction.
3047 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3048 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
3049 }
3050
3051 if (UseTraps)
3052 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3053 else {
3054 // Branch to the mflo instruction.
3055 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3056 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3057 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3058 }
3059 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3060 return false;
3061}
3062
Daniel Sanders6394ee52015-10-15 14:52:58 +00003063bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3064 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003065 if (hasMips32r6() || hasMips64r6()) {
3066 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3067 return false;
3068 }
3069
3070 warnIfNoMacro(IDLoc);
3071
3072 const MCOperand &DstRegOp = Inst.getOperand(0);
3073 assert(DstRegOp.isReg() && "expected register operand kind");
3074
3075 const MCOperand &SrcRegOp = Inst.getOperand(1);
3076 assert(SrcRegOp.isReg() && "expected register operand kind");
3077
3078 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3079 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3080
3081 unsigned DstReg = DstRegOp.getReg();
3082 unsigned SrcReg = SrcRegOp.getReg();
3083 int64_t OffsetValue = OffsetImmOp.getImm();
3084
3085 // NOTE: We always need AT for ULHU, as it is always used as the source
3086 // register for one of the LBu's.
3087 unsigned ATReg = getATReg(IDLoc);
3088 if (!ATReg)
3089 return true;
3090
3091 // When the value of offset+1 does not fit in 16 bits, we have to load the
3092 // offset in AT, (D)ADDu the original source register (if there was one), and
3093 // then use AT as the source register for the 2 generated LBu's.
3094 bool LoadedOffsetInAT = false;
3095 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3096 LoadedOffsetInAT = true;
3097
3098 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003099 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003100 return true;
3101
3102 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3103 // because it will make our output more similar to GAS'. For example,
3104 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3105 // instead of just an "ori $1, $9, 32768".
3106 // NOTE: If there is no source register specified in the ULHU, the parser
3107 // will interpret it as $0.
3108 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3109 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3110 }
3111
3112 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3113 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3114 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3115
3116 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3117 if (isLittle()) {
3118 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3119 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3120 } else {
3121 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3122 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3123 }
3124
3125 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3126
Daniel Sanders6394ee52015-10-15 14:52:58 +00003127 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3128 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003129
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003130 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3131 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003132
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003133 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003134
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003135 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003136
3137 return false;
3138}
3139
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003140bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3141 SmallVectorImpl<MCInst> &Instructions) {
3142 if (hasMips32r6() || hasMips64r6()) {
3143 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3144 return false;
3145 }
3146
3147 const MCOperand &DstRegOp = Inst.getOperand(0);
3148 assert(DstRegOp.isReg() && "expected register operand kind");
3149
3150 const MCOperand &SrcRegOp = Inst.getOperand(1);
3151 assert(SrcRegOp.isReg() && "expected register operand kind");
3152
3153 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3154 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3155
3156 unsigned SrcReg = SrcRegOp.getReg();
3157 int64_t OffsetValue = OffsetImmOp.getImm();
3158 unsigned ATReg = 0;
3159
3160 // When the value of offset+3 does not fit in 16 bits, we have to load the
3161 // offset in AT, (D)ADDu the original source register (if there was one), and
3162 // then use AT as the source register for the generated LWL and LWR.
3163 bool LoadedOffsetInAT = false;
3164 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3165 ATReg = getATReg(IDLoc);
3166 if (!ATReg)
3167 return true;
3168 LoadedOffsetInAT = true;
3169
3170 warnIfNoMacro(IDLoc);
3171
3172 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003173 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003174 return true;
3175
3176 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3177 // because it will make our output more similar to GAS'. For example,
3178 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3179 // instead of just an "ori $1, $9, 32768".
3180 // NOTE: If there is no source register specified in the ULW, the parser
3181 // will interpret it as $0.
3182 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3183 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3184 }
3185
3186 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3187 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3188 if (isLittle()) {
3189 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3190 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3191 } else {
3192 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3193 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3194 }
3195
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003196 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3197 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003198
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003199 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3200 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003201
3202 return false;
3203}
3204
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003205bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3206 SmallVectorImpl<MCInst> &Instructions) {
3207
3208 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3209 assert (Inst.getOperand(0).isReg() &&
3210 Inst.getOperand(1).isReg() &&
3211 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3212
3213 unsigned ATReg = Mips::NoRegister;
3214 unsigned FinalDstReg = Mips::NoRegister;
3215 unsigned DstReg = Inst.getOperand(0).getReg();
3216 unsigned SrcReg = Inst.getOperand(1).getReg();
3217 int64_t ImmValue = Inst.getOperand(2).getImm();
3218
3219 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3220
3221 unsigned FinalOpcode = Inst.getOpcode();
3222
3223 if (DstReg == SrcReg) {
3224 ATReg = getATReg(Inst.getLoc());
3225 if (!ATReg)
3226 return true;
3227 FinalDstReg = DstReg;
3228 DstReg = ATReg;
3229 }
3230
3231 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3232 switch (FinalOpcode) {
3233 default:
3234 llvm_unreachable("unimplemented expansion");
3235 case (Mips::ADDi):
3236 FinalOpcode = Mips::ADD;
3237 break;
3238 case (Mips::ADDiu):
3239 FinalOpcode = Mips::ADDu;
3240 break;
3241 case (Mips::ANDi):
3242 FinalOpcode = Mips::AND;
3243 break;
3244 case (Mips::NORImm):
3245 FinalOpcode = Mips::NOR;
3246 break;
3247 case (Mips::ORi):
3248 FinalOpcode = Mips::OR;
3249 break;
3250 case (Mips::SLTi):
3251 FinalOpcode = Mips::SLT;
3252 break;
3253 case (Mips::SLTiu):
3254 FinalOpcode = Mips::SLTu;
3255 break;
3256 case (Mips::XORi):
3257 FinalOpcode = Mips::XOR;
3258 break;
3259 }
3260
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003261 if (FinalDstReg == Mips::NoRegister)
3262 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3263 else
3264 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3265 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003266 return false;
3267 }
3268 return true;
3269}
3270
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003271bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
3272 SmallVectorImpl<MCInst> &Instructions) {
3273 unsigned ATReg = Mips::NoRegister;
3274 unsigned DReg = Inst.getOperand(0).getReg();
3275 unsigned SReg = Inst.getOperand(1).getReg();
3276 unsigned TReg = Inst.getOperand(2).getReg();
3277 unsigned TmpReg = DReg;
3278
3279 unsigned FirstShift = Mips::NOP;
3280 unsigned SecondShift = Mips::NOP;
3281
3282 if (hasMips32r2()) {
3283
3284 if (DReg == SReg) {
3285 TmpReg = getATReg(Inst.getLoc());
3286 if (!TmpReg)
3287 return true;
3288 }
3289
3290 if (Inst.getOpcode() == Mips::ROL) {
3291 emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3292 emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3293 return false;
3294 }
3295
3296 if (Inst.getOpcode() == Mips::ROR) {
3297 emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3298 return false;
3299 }
3300
3301 return true;
3302 }
3303
3304 if (hasMips32()) {
3305
3306 switch (Inst.getOpcode()) {
3307 default:
3308 llvm_unreachable("unexpected instruction opcode");
3309 case Mips::ROL:
3310 FirstShift = Mips::SRLV;
3311 SecondShift = Mips::SLLV;
3312 break;
3313 case Mips::ROR:
3314 FirstShift = Mips::SLLV;
3315 SecondShift = Mips::SRLV;
3316 break;
3317 }
3318
3319 ATReg = getATReg(Inst.getLoc());
3320 if (!ATReg)
3321 return true;
3322
3323 emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3324 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3325 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3326 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3327
3328 return false;
3329 }
3330
3331 return true;
3332}
3333
3334bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
3335 SmallVectorImpl<MCInst> &Instructions) {
3336
3337 unsigned ATReg = Mips::NoRegister;
3338 unsigned DReg = Inst.getOperand(0).getReg();
3339 unsigned SReg = Inst.getOperand(1).getReg();
3340 int64_t ImmValue = Inst.getOperand(2).getImm();
3341
3342 unsigned FirstShift = Mips::NOP;
3343 unsigned SecondShift = Mips::NOP;
3344
3345 if (hasMips32r2()) {
3346
3347 if (Inst.getOpcode() == Mips::ROLImm) {
3348 uint64_t MaxShift = 32;
3349 uint64_t ShiftValue = ImmValue;
3350 if (ImmValue != 0)
3351 ShiftValue = MaxShift - ImmValue;
3352 emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3353 return false;
3354 }
3355
3356 if (Inst.getOpcode() == Mips::RORImm) {
3357 emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3358 return false;
3359 }
3360
3361 return true;
3362 }
3363
3364 if (hasMips32()) {
3365
3366 if (ImmValue == 0) {
3367 emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3368 return false;
3369 }
3370
3371 switch (Inst.getOpcode()) {
3372 default:
3373 llvm_unreachable("unexpected instruction opcode");
3374 case Mips::ROLImm:
3375 FirstShift = Mips::SLL;
3376 SecondShift = Mips::SRL;
3377 break;
3378 case Mips::RORImm:
3379 FirstShift = Mips::SRL;
3380 SecondShift = Mips::SLL;
3381 break;
3382 }
3383
3384 ATReg = getATReg(Inst.getLoc());
3385 if (!ATReg)
3386 return true;
3387
3388 emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3389 emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions);
3390 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3391
3392 return false;
3393 }
3394
3395 return true;
3396}
3397
3398bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
3399 SmallVectorImpl<MCInst> &Instructions) {
3400
3401 unsigned ATReg = Mips::NoRegister;
3402 unsigned DReg = Inst.getOperand(0).getReg();
3403 unsigned SReg = Inst.getOperand(1).getReg();
3404 unsigned TReg = Inst.getOperand(2).getReg();
3405 unsigned TmpReg = DReg;
3406
3407 unsigned FirstShift = Mips::NOP;
3408 unsigned SecondShift = Mips::NOP;
3409
3410 if (hasMips64r2()) {
3411
3412 if (TmpReg == SReg) {
3413 TmpReg = getATReg(Inst.getLoc());
3414 if (!TmpReg)
3415 return true;
3416 }
3417
3418 if (Inst.getOpcode() == Mips::DROL) {
3419 emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3420 emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3421 return false;
3422 }
3423
3424 if (Inst.getOpcode() == Mips::DROR) {
3425 emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3426 return false;
3427 }
3428
3429 return true;
3430 }
3431
3432 if (hasMips64()) {
3433
3434 switch (Inst.getOpcode()) {
3435 default:
3436 llvm_unreachable("unexpected instruction opcode");
3437 case Mips::DROL:
3438 FirstShift = Mips::DSRLV;
3439 SecondShift = Mips::DSLLV;
3440 break;
3441 case Mips::DROR:
3442 FirstShift = Mips::DSLLV;
3443 SecondShift = Mips::DSRLV;
3444 break;
3445 }
3446
3447 ATReg = getATReg(Inst.getLoc());
3448 if (!ATReg)
3449 return true;
3450
3451 emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3452 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3453 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3454 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3455
3456 return false;
3457 }
3458
3459 return true;
3460}
3461
3462bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
3463 SmallVectorImpl<MCInst> &Instructions) {
3464
3465 unsigned ATReg = Mips::NoRegister;
3466 unsigned DReg = Inst.getOperand(0).getReg();
3467 unsigned SReg = Inst.getOperand(1).getReg();
3468 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3469
3470 unsigned FirstShift = Mips::NOP;
3471 unsigned SecondShift = Mips::NOP;
3472
3473 MCInst TmpInst;
3474
3475 if (hasMips64r2()) {
3476
3477 unsigned FinalOpcode = Mips::NOP;
3478 if (ImmValue == 0)
3479 FinalOpcode = Mips::DROTR;
3480 else if (ImmValue % 32 == 0)
3481 FinalOpcode = Mips::DROTR32;
3482 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3483 if (Inst.getOpcode() == Mips::DROLImm)
3484 FinalOpcode = Mips::DROTR32;
3485 else
3486 FinalOpcode = Mips::DROTR;
3487 } else if (ImmValue >= 33) {
3488 if (Inst.getOpcode() == Mips::DROLImm)
3489 FinalOpcode = Mips::DROTR;
3490 else
3491 FinalOpcode = Mips::DROTR32;
3492 }
3493
3494 uint64_t ShiftValue = ImmValue % 32;
3495 if (Inst.getOpcode() == Mips::DROLImm)
3496 ShiftValue = (32 - ImmValue % 32) % 32;
3497
3498 emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3499
3500 return false;
3501 }
3502
3503 if (hasMips64()) {
3504
3505 if (ImmValue == 0) {
3506 emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3507 return false;
3508 }
3509
3510 switch (Inst.getOpcode()) {
3511 default:
3512 llvm_unreachable("unexpected instruction opcode");
3513 case Mips::DROLImm:
3514 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3515 FirstShift = Mips::DSLL;
3516 SecondShift = Mips::DSRL32;
3517 }
3518 if (ImmValue == 32) {
3519 FirstShift = Mips::DSLL32;
3520 SecondShift = Mips::DSRL32;
3521 }
3522 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3523 FirstShift = Mips::DSLL32;
3524 SecondShift = Mips::DSRL;
3525 }
3526 break;
3527 case Mips::DRORImm:
3528 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3529 FirstShift = Mips::DSRL;
3530 SecondShift = Mips::DSLL32;
3531 }
3532 if (ImmValue == 32) {
3533 FirstShift = Mips::DSRL32;
3534 SecondShift = Mips::DSLL32;
3535 }
3536 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3537 FirstShift = Mips::DSRL32;
3538 SecondShift = Mips::DSLL;
3539 }
3540 break;
3541 }
3542
3543 ATReg = getATReg(Inst.getLoc());
3544 if (!ATReg)
3545 return true;
3546
3547 emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions);
3548 emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions);
3549 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3550
3551 return false;
3552 }
3553
3554 return true;
3555}
3556
Toma Tabacu234482a2015-03-16 12:03:39 +00003557void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3558 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003559 if (hasShortDelaySlot)
3560 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3561 else
3562 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003563}
3564
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003565void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003566 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003567 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003568 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3569 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003570}
3571
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003572void MipsAsmParser::createCpRestoreMemOp(
3573 bool IsLoad, int StackOffset, SMLoc IDLoc,
3574 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003575 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003576 if (!isInt<16>(StackOffset)) {
3577 MCInst MemInst;
3578 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3579 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3580 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3581 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003582 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003583 return;
3584 }
3585
3586 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3587 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003588}
3589
Matheus Almeida595fcab2014-06-11 15:05:56 +00003590unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3591 // As described by the Mips32r2 spec, the registers Rd and Rs for
3592 // jalr.hb must be different.
3593 unsigned Opcode = Inst.getOpcode();
3594
3595 if (Opcode == Mips::JALR_HB &&
3596 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3597 return Match_RequiresDifferentSrcAndDst;
3598
3599 return Match_Success;
3600}
3601
Daniel Sanders52da7af2015-11-06 12:11:03 +00003602static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3603 uint64_t ErrorInfo) {
3604 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3605 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3606 if (ErrorLoc == SMLoc())
3607 return Loc;
3608 return ErrorLoc;
3609 }
3610 return Loc;
3611}
3612
David Blaikie960ea3f2014-06-08 16:18:35 +00003613bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3614 OperandVector &Operands,
3615 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003616 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003617 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003618
Jack Carterb4dbc172012-09-05 23:34:03 +00003619 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003620 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003621 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003622 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003623
3624 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003625 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003626 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003627 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003628 for (unsigned i = 0; i < Instructions.size(); i++)
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003629 Out.EmitInstruction(Instructions[i], getSTI());
Jack Carterb4dbc172012-09-05 23:34:03 +00003630 return false;
3631 }
3632 case Match_MissingFeature:
3633 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3634 return true;
3635 case Match_InvalidOperand: {
3636 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003637 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003638 if (ErrorInfo >= Operands.size())
3639 return Error(IDLoc, "too few operands for instruction");
3640
Daniel Sanders52da7af2015-11-06 12:11:03 +00003641 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003642 if (ErrorLoc == SMLoc())
3643 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003644 }
3645
3646 return Error(ErrorLoc, "invalid operand for instruction");
3647 }
3648 case Match_MnemonicFail:
3649 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003650 case Match_RequiresDifferentSrcAndDst:
3651 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003652 case Match_Immz:
3653 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003654 case Match_UImm1_0:
3655 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3656 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003657 case Match_UImm2_0:
3658 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3659 "expected 2-bit unsigned immediate");
3660 case Match_UImm2_1:
3661 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3662 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003663 case Match_UImm3_0:
3664 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3665 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003666 case Match_UImm4_0:
3667 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3668 "expected 4-bit unsigned immediate");
Jack Carterb4dbc172012-09-05 23:34:03 +00003669 }
Craig Topper589ceee2015-01-03 08:16:34 +00003670
3671 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003672}
3673
Toma Tabacud9d344b2015-04-27 14:05:04 +00003674void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3675 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3676 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3677 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003678}
3679
Toma Tabacu81496c12015-05-20 08:54:45 +00003680void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3681 if (!AssemblerOptions.back()->isMacro())
3682 Warning(Loc, "macro instruction expanded into multiple instructions");
3683}
3684
Daniel Sandersef638fe2014-10-03 15:37:37 +00003685void
3686MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3687 SMRange Range, bool ShowColors) {
3688 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003689 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003690 ShowColors);
3691}
3692
Jack Carter1ac53222013-02-20 23:11:17 +00003693int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003694 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003695
Vladimir Medic4c299852013-11-06 11:27:05 +00003696 CC = StringSwitch<unsigned>(Name)
3697 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003698 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003699 .Case("a0", 4)
3700 .Case("a1", 5)
3701 .Case("a2", 6)
3702 .Case("a3", 7)
3703 .Case("v0", 2)
3704 .Case("v1", 3)
3705 .Case("s0", 16)
3706 .Case("s1", 17)
3707 .Case("s2", 18)
3708 .Case("s3", 19)
3709 .Case("s4", 20)
3710 .Case("s5", 21)
3711 .Case("s6", 22)
3712 .Case("s7", 23)
3713 .Case("k0", 26)
3714 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003715 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003716 .Case("sp", 29)
3717 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003718 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003719 .Case("ra", 31)
3720 .Case("t0", 8)
3721 .Case("t1", 9)
3722 .Case("t2", 10)
3723 .Case("t3", 11)
3724 .Case("t4", 12)
3725 .Case("t5", 13)
3726 .Case("t6", 14)
3727 .Case("t7", 15)
3728 .Case("t8", 24)
3729 .Case("t9", 25)
3730 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003731
Toma Tabacufda445c2014-09-15 15:33:01 +00003732 if (!(isABI_N32() || isABI_N64()))
3733 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003734
Daniel Sandersef638fe2014-10-03 15:37:37 +00003735 if (12 <= CC && CC <= 15) {
3736 // Name is one of t4-t7
3737 AsmToken RegTok = getLexer().peekTok();
3738 SMRange RegRange = RegTok.getLocRange();
3739
3740 StringRef FixedName = StringSwitch<StringRef>(Name)
3741 .Case("t4", "t0")
3742 .Case("t5", "t1")
3743 .Case("t6", "t2")
3744 .Case("t7", "t3")
3745 .Default("");
3746 assert(FixedName != "" && "Register name is not one of t4-t7.");
3747
3748 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3749 "Did you mean $" + FixedName + "?", RegRange);
3750 }
3751
Toma Tabacufda445c2014-09-15 15:33:01 +00003752 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3753 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3754 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3755 if (8 <= CC && CC <= 11)
3756 CC += 4;
3757
3758 if (CC == -1)
3759 CC = StringSwitch<unsigned>(Name)
3760 .Case("a4", 8)
3761 .Case("a5", 9)
3762 .Case("a6", 10)
3763 .Case("a7", 11)
3764 .Case("kt0", 26)
3765 .Case("kt1", 27)
3766 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003767
3768 return CC;
3769}
Jack Carterd0bd6422013-04-18 00:41:53 +00003770
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003771int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3772 int CC;
3773
3774 CC = StringSwitch<unsigned>(Name)
3775 .Case("hwr_cpunum", 0)
3776 .Case("hwr_synci_step", 1)
3777 .Case("hwr_cc", 2)
3778 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003779 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003780 .Default(-1);
3781
3782 return CC;
3783}
3784
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003785int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003786
Jack Cartera63b16a2012-09-07 00:23:42 +00003787 if (Name[0] == 'f') {
3788 StringRef NumString = Name.substr(1);
3789 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003790 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003791 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003792 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003793 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003794 return IntVal;
3795 }
3796 return -1;
3797}
Jack Cartera63b16a2012-09-07 00:23:42 +00003798
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003799int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3800
3801 if (Name.startswith("fcc")) {
3802 StringRef NumString = Name.substr(3);
3803 unsigned IntVal;
3804 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003805 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003806 if (IntVal > 7) // There are only 8 fcc registers.
3807 return -1;
3808 return IntVal;
3809 }
3810 return -1;
3811}
3812
3813int MipsAsmParser::matchACRegisterName(StringRef Name) {
3814
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003815 if (Name.startswith("ac")) {
3816 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003817 unsigned IntVal;
3818 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003819 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003820 if (IntVal > 3) // There are only 3 acc registers.
3821 return -1;
3822 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003823 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003824 return -1;
3825}
Jack Carterd0bd6422013-04-18 00:41:53 +00003826
Jack Carter5dc8ac92013-09-25 23:50:44 +00003827int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3828 unsigned IntVal;
3829
3830 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3831 return -1;
3832
3833 if (IntVal > 31)
3834 return -1;
3835
3836 return IntVal;
3837}
3838
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003839int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3840 int CC;
3841
3842 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003843 .Case("msair", 0)
3844 .Case("msacsr", 1)
3845 .Case("msaaccess", 2)
3846 .Case("msasave", 3)
3847 .Case("msamodify", 4)
3848 .Case("msarequest", 5)
3849 .Case("msamap", 6)
3850 .Case("msaunmap", 7)
3851 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003852
3853 return CC;
3854}
3855
Toma Tabacu89a712b2015-04-15 10:48:56 +00003856unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003857 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003858 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003859 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003860 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003861 return 0;
3862 }
3863 unsigned AT = getReg(
3864 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003865 return AT;
3866}
Jack Carter0b744b32012-10-04 02:29:46 +00003867
Jack Carterd0bd6422013-04-18 00:41:53 +00003868unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003869 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003870}
3871
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003872unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003873 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003874 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003875}
3876
Jack Carter873c7242013-01-12 01:03:14 +00003877int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003878 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003879 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003880 return -1;
3881
Jack Carter873c7242013-01-12 01:03:14 +00003882 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003883}
3884
Toma Tabacu13964452014-09-04 13:23:44 +00003885bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003886 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003887 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003888
Jack Carter30a59822012-10-04 04:03:53 +00003889 // Check if the current operand has a custom associated parser, if so, try to
3890 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003891 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3892 if (ResTy == MatchOperand_Success)
3893 return false;
3894 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3895 // there was a match, but an error occurred, in which case, just return that
3896 // the operand parsing failed.
3897 if (ResTy == MatchOperand_ParseFail)
3898 return true;
3899
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003900 DEBUG(dbgs() << ".. Generic Parser\n");
3901
Jack Carterb4dbc172012-09-05 23:34:03 +00003902 switch (getLexer().getKind()) {
3903 default:
3904 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3905 return true;
3906 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003907 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003908 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003909
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003910 // Almost all registers have been parsed by custom parsers. There is only
3911 // one exception to this. $zero (and it's alias $0) will reach this point
3912 // for div, divu, and similar instructions because it is not an operand
3913 // to the instruction definition but an explicit register. Special case
3914 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003915 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003916 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003917
Jack Carterd0bd6422013-04-18 00:41:53 +00003918 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003919 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003920 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003921 return true;
3922
Jack Carter873c7242013-01-12 01:03:14 +00003923 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003924 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003925 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003926 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003927 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003928
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003929 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003930 return false;
3931 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003932 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003933 case AsmToken::LParen:
3934 case AsmToken::Minus:
3935 case AsmToken::Plus:
3936 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003937 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003938 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003939 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003940 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003941 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003942 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003943 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003944 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003945 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003946 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003947 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003948 return true;
3949
Jack Carter873c7242013-01-12 01:03:14 +00003950 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3951
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003952 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003953 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003954 } // case AsmToken::Percent
3955 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003956 return true;
3957}
3958
Vladimir Medic4c299852013-11-06 11:27:05 +00003959const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003960 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003961 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003962 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003963 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003964 // It's a constant, evaluate reloc value.
3965 int16_t Val;
3966 switch (getVariantKind(RelocStr)) {
3967 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3968 // Get the 1st 16-bits.
3969 Val = MCE->getValue() & 0xffff;
3970 break;
3971 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3972 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3973 // 16 bits being negative.
3974 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3975 break;
3976 case MCSymbolRefExpr::VK_Mips_HIGHER:
3977 // Get the 3rd 16-bits.
3978 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3979 break;
3980 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3981 // Get the 4th 16-bits.
3982 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3983 break;
3984 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003985 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003986 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003987 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003988 }
3989
Jack Carterb5cf5902013-04-17 00:18:04 +00003990 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003991 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003992 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003993 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003994 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003995 return Res;
3996 }
3997
3998 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003999 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
4000
Sasa Stankovic06c47802014-04-03 10:37:45 +00004001 // Try to create target expression.
4002 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00004003 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004004
Jack Carterd0bd6422013-04-18 00:41:53 +00004005 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
4006 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004007 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004008 return Res;
4009 }
4010
4011 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004012 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004013 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00004014 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00004015 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004016 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004017 return Expr;
4018}
4019
4020bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4021
4022 switch (Expr->getKind()) {
4023 case MCExpr::Constant:
4024 return true;
4025 case MCExpr::SymbolRef:
4026 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4027 case MCExpr::Binary:
4028 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4029 if (!isEvaluated(BE->getLHS()))
4030 return false;
4031 return isEvaluated(BE->getRHS());
4032 }
4033 case MCExpr::Unary:
4034 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004035 case MCExpr::Target:
4036 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004037 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004038 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004039}
Jack Carterd0bd6422013-04-18 00:41:53 +00004040
Jack Carterb5cf5902013-04-17 00:18:04 +00004041bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004042 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004043 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004044 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004045 if (Tok.isNot(AsmToken::Identifier))
4046 return true;
4047
Yaron Keren075759a2015-03-30 15:42:36 +00004048 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004049
Jack Carterd0bd6422013-04-18 00:41:53 +00004050 Parser.Lex(); // Eat the identifier.
4051 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004052 const MCExpr *IdVal;
4053 SMLoc EndLoc;
4054
4055 if (getLexer().getKind() == AsmToken::LParen) {
4056 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004057 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004058 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004059 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004060 const AsmToken &nextTok = Parser.getTok();
4061 if (nextTok.isNot(AsmToken::Identifier))
4062 return true;
4063 Str += "(%";
4064 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004065 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004066 if (getLexer().getKind() != AsmToken::LParen)
4067 return true;
4068 } else
4069 break;
4070 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004071 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004072 return true;
4073
4074 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004075 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004076
4077 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004078 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004079
Jack Carterd0bd6422013-04-18 00:41:53 +00004080 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004081 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004082}
4083
Jack Carterb4dbc172012-09-05 23:34:03 +00004084bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4085 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004086 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004087 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004088 if (ResTy == MatchOperand_Success) {
4089 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004090 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004091 StartLoc = Operand.getStartLoc();
4092 EndLoc = Operand.getEndLoc();
4093
4094 // AFAIK, we only support numeric registers and named GPR's in CFI
4095 // directives.
4096 // Don't worry about eating tokens before failing. Using an unrecognised
4097 // register is a parse error.
4098 if (Operand.isGPRAsmReg()) {
4099 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004100 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004101 }
4102
4103 return (RegNo == (unsigned)-1);
4104 }
4105
4106 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004107 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004108}
4109
Jack Carterb5cf5902013-04-17 00:18:04 +00004110bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004111 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004112 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004113 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004114 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004115
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004116 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004117 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004118 ++NumOfLParen;
4119 }
Jack Carter873c7242013-01-12 01:03:14 +00004120
Jack Carterd0bd6422013-04-18 00:41:53 +00004121 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004122 default:
4123 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004124 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004125 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004126 case AsmToken::Integer:
4127 case AsmToken::Minus:
4128 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004129 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004130 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004131 else
4132 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004133 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004134 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004135 break;
Jack Carter873c7242013-01-12 01:03:14 +00004136 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004137 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004138 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004139 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004140}
4141
David Blaikie960ea3f2014-06-08 16:18:35 +00004142MipsAsmParser::OperandMatchResultTy
4143MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004144 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004145 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004146 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004147 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004148 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004149 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004150 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004151 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004152
Jack Carterb5cf5902013-04-17 00:18:04 +00004153 if (getLexer().getKind() == AsmToken::LParen) {
4154 Parser.Lex();
4155 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004156 }
4157
Jack Carterb5cf5902013-04-17 00:18:04 +00004158 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004159 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004160 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004161
Jack Carterd0bd6422013-04-18 00:41:53 +00004162 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004163 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004164 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004165 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004166 SMLoc E =
4167 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004168 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004169 return MatchOperand_Success;
4170 }
4171 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004172 SMLoc E =
4173 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004174
Jack Carterd0bd6422013-04-18 00:41:53 +00004175 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004176 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004177 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004178 S, E, *this);
4179 Operands.push_back(
4180 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004181 return MatchOperand_Success;
4182 }
4183 Error(Parser.getTok().getLoc(), "'(' expected");
4184 return MatchOperand_ParseFail;
4185 }
4186
Jack Carterd0bd6422013-04-18 00:41:53 +00004187 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004188 }
4189
Toma Tabacu13964452014-09-04 13:23:44 +00004190 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004191 if (Res != MatchOperand_Success)
4192 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004193
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004194 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004195 Error(Parser.getTok().getLoc(), "')' expected");
4196 return MatchOperand_ParseFail;
4197 }
4198
Jack Carter873c7242013-01-12 01:03:14 +00004199 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4200
Jack Carterd0bd6422013-04-18 00:41:53 +00004201 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004202
Craig Topper062a2ba2014-04-25 05:30:21 +00004203 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004204 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004205
Jack Carterd0bd6422013-04-18 00:41:53 +00004206 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004207 std::unique_ptr<MipsOperand> op(
4208 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004209 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004210 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004211 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004212 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004213 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4214 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004215 if (IdVal->evaluateAsAbsolute(Imm))
4216 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004217 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004218 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004219 getContext());
4220 }
4221
David Blaikie960ea3f2014-06-08 16:18:35 +00004222 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004223 return MatchOperand_Success;
4224}
4225
David Blaikie960ea3f2014-06-08 16:18:35 +00004226bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004227 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004228 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004229 if (Sym) {
4230 SMLoc S = Parser.getTok().getLoc();
4231 const MCExpr *Expr;
4232 if (Sym->isVariable())
4233 Expr = Sym->getVariableValue();
4234 else
4235 return false;
4236 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004237 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004238 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004239 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004240 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004241 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004242 if (ResTy == MatchOperand_Success) {
4243 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004244 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004245 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004246 llvm_unreachable("Should never ParseFail");
4247 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004248 }
4249 } else if (Expr->getKind() == MCExpr::Constant) {
4250 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004251 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004252 Operands.push_back(
4253 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004254 return true;
4255 }
4256 }
4257 return false;
4258}
Jack Carterd0bd6422013-04-18 00:41:53 +00004259
Jack Carter873c7242013-01-12 01:03:14 +00004260MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004261MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004262 StringRef Identifier,
4263 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004264 int Index = matchCPURegisterName(Identifier);
4265 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004266 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004267 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4268 return MatchOperand_Success;
4269 }
4270
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004271 Index = matchHWRegsRegisterName(Identifier);
4272 if (Index != -1) {
4273 Operands.push_back(MipsOperand::createHWRegsReg(
4274 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4275 return MatchOperand_Success;
4276 }
4277
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004278 Index = matchFPURegisterName(Identifier);
4279 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004280 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004281 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4282 return MatchOperand_Success;
4283 }
4284
4285 Index = matchFCCRegisterName(Identifier);
4286 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004287 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004288 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4289 return MatchOperand_Success;
4290 }
4291
4292 Index = matchACRegisterName(Identifier);
4293 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004294 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004295 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4296 return MatchOperand_Success;
4297 }
4298
4299 Index = matchMSA128RegisterName(Identifier);
4300 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004301 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004302 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4303 return MatchOperand_Success;
4304 }
4305
4306 Index = matchMSA128CtrlRegisterName(Identifier);
4307 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004308 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004309 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4310 return MatchOperand_Success;
4311 }
4312
4313 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004314}
4315
4316MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004317MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004318 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004319 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004320
4321 if (Token.is(AsmToken::Identifier)) {
4322 DEBUG(dbgs() << ".. identifier\n");
4323 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004324 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004325 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004326 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004327 } else if (Token.is(AsmToken::Integer)) {
4328 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004329 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004330 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4331 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004332 return MatchOperand_Success;
4333 }
4334
4335 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4336
4337 return MatchOperand_NoMatch;
4338}
4339
David Blaikie960ea3f2014-06-08 16:18:35 +00004340MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004341MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004342 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004343 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004344
4345 auto Token = Parser.getTok();
4346
4347 SMLoc S = Token.getLoc();
4348
4349 if (Token.isNot(AsmToken::Dollar)) {
4350 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4351 if (Token.is(AsmToken::Identifier)) {
4352 if (searchSymbolAlias(Operands))
4353 return MatchOperand_Success;
4354 }
4355 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4356 return MatchOperand_NoMatch;
4357 }
4358 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004359
Toma Tabacu13964452014-09-04 13:23:44 +00004360 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004361 if (ResTy == MatchOperand_Success) {
4362 Parser.Lex(); // $
4363 Parser.Lex(); // identifier
4364 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004365 return ResTy;
4366}
4367
4368MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004369MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004370 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004371 switch (getLexer().getKind()) {
4372 default:
4373 return MatchOperand_NoMatch;
4374 case AsmToken::LParen:
4375 case AsmToken::Minus:
4376 case AsmToken::Plus:
4377 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004378 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004379 case AsmToken::String:
4380 break;
4381 }
4382
4383 const MCExpr *IdVal;
4384 SMLoc S = Parser.getTok().getLoc();
4385 if (getParser().parseExpression(IdVal))
4386 return MatchOperand_ParseFail;
4387
4388 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4389 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4390 return MatchOperand_Success;
4391}
4392
David Blaikie960ea3f2014-06-08 16:18:35 +00004393MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004394MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004395 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004396 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004397
4398 SMLoc S = getLexer().getLoc();
4399
4400 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004401 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004402 if (ResTy != MatchOperand_NoMatch)
4403 return ResTy;
4404
Daniel Sanders315386c2014-04-01 10:40:14 +00004405 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004406 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004407 if (ResTy != MatchOperand_NoMatch)
4408 return ResTy;
4409
Daniel Sandersffd84362014-04-01 10:41:48 +00004410 const MCExpr *Expr = nullptr;
4411 if (Parser.parseExpression(Expr)) {
4412 // We have no way of knowing if a symbol was consumed so we must ParseFail
4413 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004414 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004415 Operands.push_back(
4416 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004417 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004418}
4419
Vladimir Medic2b953d02013-10-01 09:48:56 +00004420MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004421MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004422 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004423 const MCExpr *IdVal;
4424 // If the first token is '$' we may have register operand.
4425 if (Parser.getTok().is(AsmToken::Dollar))
4426 return MatchOperand_NoMatch;
4427 SMLoc S = Parser.getTok().getLoc();
4428 if (getParser().parseExpression(IdVal))
4429 return MatchOperand_ParseFail;
4430 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004431 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004432 int64_t Val = MCE->getValue();
4433 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4434 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004435 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004436 return MatchOperand_Success;
4437}
4438
Matheus Almeida779c5932013-11-18 12:32:49 +00004439MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004440MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004441 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004442 switch (getLexer().getKind()) {
4443 default:
4444 return MatchOperand_NoMatch;
4445 case AsmToken::LParen:
4446 case AsmToken::Plus:
4447 case AsmToken::Minus:
4448 case AsmToken::Integer:
4449 break;
4450 }
4451
4452 const MCExpr *Expr;
4453 SMLoc S = Parser.getTok().getLoc();
4454
4455 if (getParser().parseExpression(Expr))
4456 return MatchOperand_ParseFail;
4457
4458 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004459 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004460 Error(S, "expected immediate value");
4461 return MatchOperand_ParseFail;
4462 }
4463
4464 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4465 // and because the CPU always adds one to the immediate field, the allowed
4466 // range becomes 1..4. We'll only check the range here and will deal
4467 // with the addition/subtraction when actually decoding/encoding
4468 // the instruction.
4469 if (Val < 1 || Val > 4) {
4470 Error(S, "immediate not in range (1..4)");
4471 return MatchOperand_ParseFail;
4472 }
4473
Jack Carter3b2c96e2014-01-22 23:31:38 +00004474 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004475 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004476 return MatchOperand_Success;
4477}
4478
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004479MipsAsmParser::OperandMatchResultTy
4480MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4481 MCAsmParser &Parser = getParser();
4482 SmallVector<unsigned, 10> Regs;
4483 unsigned RegNo;
4484 unsigned PrevReg = Mips::NoRegister;
4485 bool RegRange = false;
4486 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4487
4488 if (Parser.getTok().isNot(AsmToken::Dollar))
4489 return MatchOperand_ParseFail;
4490
4491 SMLoc S = Parser.getTok().getLoc();
4492 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4493 SMLoc E = getLexer().getLoc();
4494 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4495 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4496 if (RegRange) {
4497 // Remove last register operand because registers from register range
4498 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004499 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4500 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004501 Regs.push_back(RegNo);
4502 } else {
4503 unsigned TmpReg = PrevReg + 1;
4504 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004505 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4506 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4507 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004508 Error(E, "invalid register operand");
4509 return MatchOperand_ParseFail;
4510 }
4511
4512 PrevReg = TmpReg;
4513 Regs.push_back(TmpReg++);
4514 }
4515 }
4516
4517 RegRange = false;
4518 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004519 if ((PrevReg == Mips::NoRegister) &&
4520 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4521 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004522 Error(E, "$16 or $31 expected");
4523 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004524 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4525 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4526 !isGP64bit()) ||
4527 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4528 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4529 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004530 Error(E, "invalid register operand");
4531 return MatchOperand_ParseFail;
4532 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004533 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4534 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4535 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004536 Error(E, "consecutive register numbers expected");
4537 return MatchOperand_ParseFail;
4538 }
4539
4540 Regs.push_back(RegNo);
4541 }
4542
4543 if (Parser.getTok().is(AsmToken::Minus))
4544 RegRange = true;
4545
4546 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4547 !Parser.getTok().isNot(AsmToken::Comma)) {
4548 Error(E, "',' or '-' expected");
4549 return MatchOperand_ParseFail;
4550 }
4551
4552 Lex(); // Consume comma or minus
4553 if (Parser.getTok().isNot(AsmToken::Dollar))
4554 break;
4555
4556 PrevReg = RegNo;
4557 }
4558
4559 SMLoc E = Parser.getTok().getLoc();
4560 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4561 parseMemOperand(Operands);
4562 return MatchOperand_Success;
4563}
4564
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004565MipsAsmParser::OperandMatchResultTy
4566MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4567 MCAsmParser &Parser = getParser();
4568
4569 SMLoc S = Parser.getTok().getLoc();
4570 if (parseAnyRegister(Operands) != MatchOperand_Success)
4571 return MatchOperand_ParseFail;
4572
4573 SMLoc E = Parser.getTok().getLoc();
4574 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4575 unsigned Reg = Op.getGPR32Reg();
4576 Operands.pop_back();
4577 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4578 return MatchOperand_Success;
4579}
4580
Zoran Jovanovic41688672015-02-10 16:36:20 +00004581MipsAsmParser::OperandMatchResultTy
4582MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4583 MCAsmParser &Parser = getParser();
4584 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4585 SmallVector<unsigned, 10> Regs;
4586
4587 if (Parser.getTok().isNot(AsmToken::Dollar))
4588 return MatchOperand_ParseFail;
4589
4590 SMLoc S = Parser.getTok().getLoc();
4591
4592 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4593 return MatchOperand_ParseFail;
4594
4595 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4596 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4597 Regs.push_back(RegNo);
4598
4599 SMLoc E = Parser.getTok().getLoc();
4600 if (Parser.getTok().isNot(AsmToken::Comma)) {
4601 Error(E, "',' expected");
4602 return MatchOperand_ParseFail;
4603 }
4604
4605 // Remove comma.
4606 Parser.Lex();
4607
4608 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4609 return MatchOperand_ParseFail;
4610
4611 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4612 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4613 Regs.push_back(RegNo);
4614
4615 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4616
4617 return MatchOperand_Success;
4618}
4619
Jack Carterdc1e35d2012-09-06 20:00:02 +00004620MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4621
Vladimir Medic4c299852013-11-06 11:27:05 +00004622 MCSymbolRefExpr::VariantKind VK =
4623 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4624 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4625 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4626 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4627 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4628 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4629 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4630 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4631 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4632 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4633 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4634 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4635 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4636 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4637 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4638 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4639 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4640 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004641 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4642 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4643 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4644 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4645 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4646 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004647 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4648 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004649 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004650
Matheus Almeida2852af82014-04-22 10:15:54 +00004651 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004652
Jack Carterdc1e35d2012-09-06 20:00:02 +00004653 return VK;
4654}
Jack Cartera63b16a2012-09-07 00:23:42 +00004655
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004656/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4657/// either this.
4658/// ::= '(', register, ')'
4659/// handle it before we iterate so we don't get tripped up by the lack of
4660/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004661bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004662 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004663 if (getLexer().is(AsmToken::LParen)) {
4664 Operands.push_back(
4665 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4666 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004667 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004668 SMLoc Loc = getLexer().getLoc();
4669 Parser.eatToEndOfStatement();
4670 return Error(Loc, "unexpected token in argument list");
4671 }
4672 if (Parser.getTok().isNot(AsmToken::RParen)) {
4673 SMLoc Loc = getLexer().getLoc();
4674 Parser.eatToEndOfStatement();
4675 return Error(Loc, "unexpected token, expected ')'");
4676 }
4677 Operands.push_back(
4678 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4679 Parser.Lex();
4680 }
4681 return false;
4682}
4683
4684/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4685/// either one of these.
4686/// ::= '[', register, ']'
4687/// ::= '[', integer, ']'
4688/// handle it before we iterate so we don't get tripped up by the lack of
4689/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004690bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004691 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004692 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004693 if (getLexer().is(AsmToken::LBrac)) {
4694 Operands.push_back(
4695 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4696 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004697 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004698 SMLoc Loc = getLexer().getLoc();
4699 Parser.eatToEndOfStatement();
4700 return Error(Loc, "unexpected token in argument list");
4701 }
4702 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4703 SMLoc Loc = getLexer().getLoc();
4704 Parser.eatToEndOfStatement();
4705 return Error(Loc, "unexpected token, expected ']'");
4706 }
4707 Operands.push_back(
4708 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4709 Parser.Lex();
4710 }
4711 return false;
4712}
4713
David Blaikie960ea3f2014-06-08 16:18:35 +00004714bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4715 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004716 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004717 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004718
4719 // We have reached first instruction, module directive are now forbidden.
4720 getTargetStreamer().forbidModuleDirective();
4721
Vladimir Medic74593e62013-07-17 15:00:42 +00004722 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004723 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004724 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004725 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004726 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004727 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004728 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004729
4730 // Read the remaining operands.
4731 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4732 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004733 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004734 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004735 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004736 return Error(Loc, "unexpected token in argument list");
4737 }
Toma Tabacu13964452014-09-04 13:23:44 +00004738 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004739 return true;
4740 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004741
Jack Carterd0bd6422013-04-18 00:41:53 +00004742 while (getLexer().is(AsmToken::Comma)) {
4743 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004744 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004745 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004746 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004747 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004748 return Error(Loc, "unexpected token in argument list");
4749 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004750 // Parse bracket and parenthesis suffixes before we iterate
4751 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004752 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004753 return true;
4754 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004755 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004756 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004757 }
4758 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004759 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4760 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004761 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004762 return Error(Loc, "unexpected token in argument list");
4763 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004764 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004765 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004766}
4767
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004768bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004769 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004770 SMLoc Loc = getLexer().getLoc();
4771 Parser.eatToEndOfStatement();
4772 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004773}
4774
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004775bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004776 return Error(Loc, ErrorMsg);
4777}
4778
Jack Carter0b744b32012-10-04 02:29:46 +00004779bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004780 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004781 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004782
4783 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004784 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004785
4786 Parser.Lex(); // Eat "noat".
4787
Jack Carterd0bd6422013-04-18 00:41:53 +00004788 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004789 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004790 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004791 return false;
4792 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004793
4794 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004795 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004796 return false;
4797}
Jack Carterd0bd6422013-04-18 00:41:53 +00004798
Jack Carter0b744b32012-10-04 02:29:46 +00004799bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004800 // Line can be: ".set at", which sets $at to $1
4801 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004802 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004803 Parser.Lex(); // Eat "at".
4804
Jack Carter0b744b32012-10-04 02:29:46 +00004805 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004806 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004807 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004808
4809 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004810 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004811 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004812 }
4813
4814 if (getLexer().isNot(AsmToken::Equal)) {
4815 reportParseError("unexpected token, expected equals sign");
4816 return false;
4817 }
4818 Parser.Lex(); // Eat "=".
4819
4820 if (getLexer().isNot(AsmToken::Dollar)) {
4821 if (getLexer().is(AsmToken::EndOfStatement)) {
4822 reportParseError("no register specified");
4823 return false;
4824 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004825 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004826 return false;
4827 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004828 }
4829 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004830
Toma Tabacu16a74492015-02-13 10:30:57 +00004831 // Find out what "reg" is.
4832 unsigned AtRegNo;
4833 const AsmToken &Reg = Parser.getTok();
4834 if (Reg.is(AsmToken::Identifier)) {
4835 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4836 } else if (Reg.is(AsmToken::Integer)) {
4837 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004838 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004839 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004840 return false;
4841 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004842
4843 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004844 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004845 reportParseError("invalid register");
4846 return false;
4847 }
4848 Parser.Lex(); // Eat "reg".
4849
4850 // If this is not the end of the statement, report an error.
4851 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4852 reportParseError("unexpected token, expected end of statement");
4853 return false;
4854 }
4855
4856 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4857
4858 Parser.Lex(); // Consume the EndOfStatement.
4859 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004860}
4861
4862bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004863 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004864 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004865 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004866 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004867 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004868 return false;
4869 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004870 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004871 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004872 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004873 return false;
4874}
4875
4876bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004877 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004878 Parser.Lex();
4879 // If this is not the end of the statement, report an error.
4880 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004881 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004882 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004883 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004884 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004885 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004886 Parser.Lex(); // Consume the EndOfStatement.
4887 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004888}
4889
4890bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004891 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004892 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004893 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004894 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004895 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004896 return false;
4897 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004898 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004899 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004900 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004901 return false;
4902}
4903
4904bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004905 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004906 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004907 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004908 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004909 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004910 return false;
4911 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004912 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004913 reportParseError("`noreorder' must be set before `nomacro'");
4914 return false;
4915 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004916 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004917 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004918 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004919 return false;
4920}
Jack Carterd76b2372013-03-21 21:44:16 +00004921
Daniel Sanders44934432014-08-07 12:03:36 +00004922bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004923 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004924 Parser.Lex();
4925
4926 // If this is not the end of the statement, report an error.
4927 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004928 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004929
4930 setFeatureBits(Mips::FeatureMSA, "msa");
4931 getTargetStreamer().emitDirectiveSetMsa();
4932 return false;
4933}
4934
4935bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004936 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004937 Parser.Lex();
4938
4939 // If this is not the end of the statement, report an error.
4940 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004941 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004942
4943 clearFeatureBits(Mips::FeatureMSA, "msa");
4944 getTargetStreamer().emitDirectiveSetNoMsa();
4945 return false;
4946}
4947
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004948bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004949 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004950 Parser.Lex(); // Eat "nodsp".
4951
4952 // If this is not the end of the statement, report an error.
4953 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4954 reportParseError("unexpected token, expected end of statement");
4955 return false;
4956 }
4957
4958 clearFeatureBits(Mips::FeatureDSP, "dsp");
4959 getTargetStreamer().emitDirectiveSetNoDsp();
4960 return false;
4961}
4962
Toma Tabacucc2502d2014-11-04 17:18:07 +00004963bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004964 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004965 Parser.Lex(); // Eat "mips16".
4966
Jack Carter39536722014-01-22 23:08:42 +00004967 // If this is not the end of the statement, report an error.
4968 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004969 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004970 return false;
4971 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004972
4973 setFeatureBits(Mips::FeatureMips16, "mips16");
4974 getTargetStreamer().emitDirectiveSetMips16();
4975 Parser.Lex(); // Consume the EndOfStatement.
4976 return false;
4977}
4978
4979bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004980 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004981 Parser.Lex(); // Eat "nomips16".
4982
4983 // If this is not the end of the statement, report an error.
4984 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4985 reportParseError("unexpected token, expected end of statement");
4986 return false;
4987 }
4988
4989 clearFeatureBits(Mips::FeatureMips16, "mips16");
4990 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004991 Parser.Lex(); // Consume the EndOfStatement.
4992 return false;
4993}
4994
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004995bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004996 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004997 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004998 // Line can be: .set fp=32
4999 // .set fp=xx
5000 // .set fp=64
5001 Parser.Lex(); // Eat fp token
5002 AsmToken Tok = Parser.getTok();
5003 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005004 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005005 return false;
5006 }
5007 Parser.Lex(); // Eat '=' token.
5008 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005009
5010 if (!parseFpABIValue(FpAbiVal, ".set"))
5011 return false;
5012
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005013 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005014 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005015 return false;
5016 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005017 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005018 Parser.Lex(); // Consume the EndOfStatement.
5019 return false;
5020}
5021
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005022bool MipsAsmParser::parseSetOddSPRegDirective() {
5023 MCAsmParser &Parser = getParser();
5024
5025 Parser.Lex(); // Eat "oddspreg".
5026 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5027 reportParseError("unexpected token, expected end of statement");
5028 return false;
5029 }
5030
5031 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5032 getTargetStreamer().emitDirectiveSetOddSPReg();
5033 return false;
5034}
5035
5036bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5037 MCAsmParser &Parser = getParser();
5038
5039 Parser.Lex(); // Eat "nooddspreg".
5040 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5041 reportParseError("unexpected token, expected end of statement");
5042 return false;
5043 }
5044
5045 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5046 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5047 return false;
5048}
5049
Toma Tabacu9db22db2014-09-09 10:15:38 +00005050bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005051 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005052 SMLoc Loc = getLexer().getLoc();
5053
5054 Parser.Lex();
5055 if (getLexer().isNot(AsmToken::EndOfStatement))
5056 return reportParseError("unexpected token, expected end of statement");
5057
5058 // Always keep an element on the options "stack" to prevent the user
5059 // from changing the initial options. This is how we remember them.
5060 if (AssemblerOptions.size() == 2)
5061 return reportParseError(Loc, ".set pop with no .set push");
5062
Akira Hatanakab11ef082015-11-14 06:35:56 +00005063 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005064 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005065 setAvailableFeatures(
5066 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5067 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005068
5069 getTargetStreamer().emitDirectiveSetPop();
5070 return false;
5071}
5072
5073bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005074 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005075 Parser.Lex();
5076 if (getLexer().isNot(AsmToken::EndOfStatement))
5077 return reportParseError("unexpected token, expected end of statement");
5078
5079 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005080 AssemblerOptions.push_back(
5081 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005082
5083 getTargetStreamer().emitDirectiveSetPush();
5084 return false;
5085}
5086
Toma Tabacu29696502015-06-02 09:48:04 +00005087bool MipsAsmParser::parseSetSoftFloatDirective() {
5088 MCAsmParser &Parser = getParser();
5089 Parser.Lex();
5090 if (getLexer().isNot(AsmToken::EndOfStatement))
5091 return reportParseError("unexpected token, expected end of statement");
5092
5093 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5094 getTargetStreamer().emitDirectiveSetSoftFloat();
5095 return false;
5096}
5097
5098bool MipsAsmParser::parseSetHardFloatDirective() {
5099 MCAsmParser &Parser = getParser();
5100 Parser.Lex();
5101 if (getLexer().isNot(AsmToken::EndOfStatement))
5102 return reportParseError("unexpected token, expected end of statement");
5103
5104 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5105 getTargetStreamer().emitDirectiveSetHardFloat();
5106 return false;
5107}
5108
Jack Carterd76b2372013-03-21 21:44:16 +00005109bool MipsAsmParser::parseSetAssignment() {
5110 StringRef Name;
5111 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005112 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005113
5114 if (Parser.parseIdentifier(Name))
5115 reportParseError("expected identifier after .set");
5116
5117 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005118 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005119 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005120
Jack Carter3b2c96e2014-01-22 23:31:38 +00005121 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005122 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005123
Jim Grosbach6f482002015-05-18 18:43:14 +00005124 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005125 Sym->setVariableValue(Value);
5126
5127 return false;
5128}
Jack Carterd0bd6422013-04-18 00:41:53 +00005129
Toma Tabacu26647792014-09-09 12:52:14 +00005130bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005131 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005132 Parser.Lex();
5133 if (getLexer().isNot(AsmToken::EndOfStatement))
5134 return reportParseError("unexpected token, expected end of statement");
5135
5136 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005137 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005138 setAvailableFeatures(
5139 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5140 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005141 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5142
5143 getTargetStreamer().emitDirectiveSetMips0();
5144 return false;
5145}
5146
Toma Tabacu85618b32014-08-19 14:22:52 +00005147bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005148 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005149 Parser.Lex();
5150 if (getLexer().isNot(AsmToken::Equal))
5151 return reportParseError("unexpected token, expected equals sign");
5152
5153 Parser.Lex();
5154 StringRef Arch;
5155 if (Parser.parseIdentifier(Arch))
5156 return reportParseError("expected arch identifier");
5157
5158 StringRef ArchFeatureName =
5159 StringSwitch<StringRef>(Arch)
5160 .Case("mips1", "mips1")
5161 .Case("mips2", "mips2")
5162 .Case("mips3", "mips3")
5163 .Case("mips4", "mips4")
5164 .Case("mips5", "mips5")
5165 .Case("mips32", "mips32")
5166 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005167 .Case("mips32r3", "mips32r3")
5168 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005169 .Case("mips32r6", "mips32r6")
5170 .Case("mips64", "mips64")
5171 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005172 .Case("mips64r3", "mips64r3")
5173 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005174 .Case("mips64r6", "mips64r6")
5175 .Case("cnmips", "cnmips")
5176 .Case("r4000", "mips3") // This is an implementation of Mips3.
5177 .Default("");
5178
5179 if (ArchFeatureName.empty())
5180 return reportParseError("unsupported architecture");
5181
5182 selectArch(ArchFeatureName);
5183 getTargetStreamer().emitDirectiveSetArch(Arch);
5184 return false;
5185}
5186
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005187bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005188 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005189 Parser.Lex();
5190 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005191 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005192
Matheus Almeida2852af82014-04-22 10:15:54 +00005193 switch (Feature) {
5194 default:
5195 llvm_unreachable("Unimplemented feature");
5196 case Mips::FeatureDSP:
5197 setFeatureBits(Mips::FeatureDSP, "dsp");
5198 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005199 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005200 case Mips::FeatureMicroMips:
5201 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005202 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005203 case Mips::FeatureMips1:
5204 selectArch("mips1");
5205 getTargetStreamer().emitDirectiveSetMips1();
5206 break;
5207 case Mips::FeatureMips2:
5208 selectArch("mips2");
5209 getTargetStreamer().emitDirectiveSetMips2();
5210 break;
5211 case Mips::FeatureMips3:
5212 selectArch("mips3");
5213 getTargetStreamer().emitDirectiveSetMips3();
5214 break;
5215 case Mips::FeatureMips4:
5216 selectArch("mips4");
5217 getTargetStreamer().emitDirectiveSetMips4();
5218 break;
5219 case Mips::FeatureMips5:
5220 selectArch("mips5");
5221 getTargetStreamer().emitDirectiveSetMips5();
5222 break;
5223 case Mips::FeatureMips32:
5224 selectArch("mips32");
5225 getTargetStreamer().emitDirectiveSetMips32();
5226 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005227 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005228 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005229 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005230 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005231 case Mips::FeatureMips32r3:
5232 selectArch("mips32r3");
5233 getTargetStreamer().emitDirectiveSetMips32R3();
5234 break;
5235 case Mips::FeatureMips32r5:
5236 selectArch("mips32r5");
5237 getTargetStreamer().emitDirectiveSetMips32R5();
5238 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005239 case Mips::FeatureMips32r6:
5240 selectArch("mips32r6");
5241 getTargetStreamer().emitDirectiveSetMips32R6();
5242 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005243 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005244 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005245 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005246 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005247 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005248 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005249 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005250 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005251 case Mips::FeatureMips64r3:
5252 selectArch("mips64r3");
5253 getTargetStreamer().emitDirectiveSetMips64R3();
5254 break;
5255 case Mips::FeatureMips64r5:
5256 selectArch("mips64r5");
5257 getTargetStreamer().emitDirectiveSetMips64R5();
5258 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005259 case Mips::FeatureMips64r6:
5260 selectArch("mips64r6");
5261 getTargetStreamer().emitDirectiveSetMips64R6();
5262 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005263 }
5264 return false;
5265}
5266
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005267bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005268 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005269 if (getLexer().isNot(AsmToken::Comma)) {
5270 SMLoc Loc = getLexer().getLoc();
5271 Parser.eatToEndOfStatement();
5272 return Error(Loc, ErrorStr);
5273 }
5274
Matheus Almeida2852af82014-04-22 10:15:54 +00005275 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005276 return true;
5277}
5278
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005279// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5280// In this class, it is only used for .cprestore.
5281// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5282// MipsTargetELFStreamer and MipsAsmParser.
5283bool MipsAsmParser::isPicAndNotNxxAbi() {
5284 return inPicMode() && !(isABI_N32() || isABI_N64());
5285}
5286
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005287bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005288 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005289 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005290
Toma Tabacudde4c462014-11-06 10:02:45 +00005291 if (inMips16Mode()) {
5292 reportParseError(".cpload is not supported in Mips16 mode");
5293 return false;
5294 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005295
David Blaikie960ea3f2014-06-08 16:18:35 +00005296 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005297 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005298 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5299 reportParseError("expected register containing function address");
5300 return false;
5301 }
5302
David Blaikie960ea3f2014-06-08 16:18:35 +00005303 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5304 if (!RegOpnd.isGPRAsmReg()) {
5305 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005306 return false;
5307 }
5308
Toma Tabacudde4c462014-11-06 10:02:45 +00005309 // If this is not the end of the statement, report an error.
5310 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5311 reportParseError("unexpected token, expected end of statement");
5312 return false;
5313 }
5314
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005315 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005316 return false;
5317}
5318
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005319bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5320 MCAsmParser &Parser = getParser();
5321
5322 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5323 // is used in non-PIC mode.
5324
5325 if (inMips16Mode()) {
5326 reportParseError(".cprestore is not supported in Mips16 mode");
5327 return false;
5328 }
5329
5330 // Get the stack offset value.
5331 const MCExpr *StackOffset;
5332 int64_t StackOffsetVal;
5333 if (Parser.parseExpression(StackOffset)) {
5334 reportParseError("expected stack offset value");
5335 return false;
5336 }
5337
5338 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5339 reportParseError("stack offset is not an absolute expression");
5340 return false;
5341 }
5342
5343 if (StackOffsetVal < 0) {
5344 Warning(Loc, ".cprestore with negative stack offset has no effect");
5345 IsCpRestoreSet = false;
5346 } else {
5347 IsCpRestoreSet = true;
5348 CpRestoreOffset = StackOffsetVal;
5349 }
5350
5351 // If this is not the end of the statement, report an error.
5352 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5353 reportParseError("unexpected token, expected end of statement");
5354 return false;
5355 }
5356
5357 // Store the $gp on the stack.
5358 SmallVector<MCInst, 3> StoreInsts;
5359 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5360 StoreInsts);
5361
5362 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5363 Parser.Lex(); // Consume the EndOfStatement.
5364 return false;
5365}
5366
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005367bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005368 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005369 unsigned FuncReg;
5370 unsigned Save;
5371 bool SaveIsReg = true;
5372
Matheus Almeida7e815762014-06-18 13:08:59 +00005373 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005374 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005375 if (ResTy == MatchOperand_NoMatch) {
5376 reportParseError("expected register containing function address");
5377 Parser.eatToEndOfStatement();
5378 return false;
5379 }
5380
5381 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5382 if (!FuncRegOpnd.isGPRAsmReg()) {
5383 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5384 Parser.eatToEndOfStatement();
5385 return false;
5386 }
5387
5388 FuncReg = FuncRegOpnd.getGPR32Reg();
5389 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005390
Toma Tabacu65f10572014-09-16 15:00:52 +00005391 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005392 return true;
5393
Toma Tabacu13964452014-09-04 13:23:44 +00005394 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005395 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005396 const MCExpr *OffsetExpr;
5397 int64_t OffsetVal;
5398 SMLoc ExprLoc = getLexer().getLoc();
5399
5400 if (Parser.parseExpression(OffsetExpr) ||
5401 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5402 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005403 Parser.eatToEndOfStatement();
5404 return false;
5405 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005406
5407 Save = OffsetVal;
5408 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005409 } else {
5410 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5411 if (!SaveOpnd.isGPRAsmReg()) {
5412 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5413 Parser.eatToEndOfStatement();
5414 return false;
5415 }
5416 Save = SaveOpnd.getGPR32Reg();
5417 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005418
Toma Tabacu65f10572014-09-16 15:00:52 +00005419 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005420 return true;
5421
Toma Tabacu8874eac2015-02-18 13:46:53 +00005422 const MCExpr *Expr;
5423 if (Parser.parseExpression(Expr)) {
5424 reportParseError("expected expression");
5425 return false;
5426 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005427
Toma Tabacu8874eac2015-02-18 13:46:53 +00005428 if (Expr->getKind() != MCExpr::SymbolRef) {
5429 reportParseError("expected symbol");
5430 return false;
5431 }
5432 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5433
Daniel Sandersf173dda2015-09-22 10:50:09 +00005434 CpSaveLocation = Save;
5435 CpSaveLocationIsRegister = SaveIsReg;
5436
Toma Tabacu8874eac2015-02-18 13:46:53 +00005437 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5438 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005439 return false;
5440}
5441
Daniel Sandersf173dda2015-09-22 10:50:09 +00005442bool MipsAsmParser::parseDirectiveCPReturn() {
5443 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5444 CpSaveLocationIsRegister);
5445 return false;
5446}
5447
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005448bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005449 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005450 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5451 const AsmToken &Tok = Parser.getTok();
5452
5453 if (Tok.getString() == "2008") {
5454 Parser.Lex();
5455 getTargetStreamer().emitDirectiveNaN2008();
5456 return false;
5457 } else if (Tok.getString() == "legacy") {
5458 Parser.Lex();
5459 getTargetStreamer().emitDirectiveNaNLegacy();
5460 return false;
5461 }
5462 }
5463 // If we don't recognize the option passed to the .nan
5464 // directive (e.g. no option or unknown option), emit an error.
5465 reportParseError("invalid option in .nan directive");
5466 return false;
5467}
5468
Jack Carter0b744b32012-10-04 02:29:46 +00005469bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005470 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005471 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005472 const AsmToken &Tok = Parser.getTok();
5473
5474 if (Tok.getString() == "noat") {
5475 return parseSetNoAtDirective();
5476 } else if (Tok.getString() == "at") {
5477 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005478 } else if (Tok.getString() == "arch") {
5479 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005480 } else if (Tok.getString() == "fp") {
5481 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005482 } else if (Tok.getString() == "oddspreg") {
5483 return parseSetOddSPRegDirective();
5484 } else if (Tok.getString() == "nooddspreg") {
5485 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005486 } else if (Tok.getString() == "pop") {
5487 return parseSetPopDirective();
5488 } else if (Tok.getString() == "push") {
5489 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005490 } else if (Tok.getString() == "reorder") {
5491 return parseSetReorderDirective();
5492 } else if (Tok.getString() == "noreorder") {
5493 return parseSetNoReorderDirective();
5494 } else if (Tok.getString() == "macro") {
5495 return parseSetMacroDirective();
5496 } else if (Tok.getString() == "nomacro") {
5497 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005498 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005499 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005500 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005501 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005502 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005503 getTargetStreamer().emitDirectiveSetNoMicroMips();
5504 Parser.eatToEndOfStatement();
5505 return false;
5506 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005507 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005508 } else if (Tok.getString() == "mips0") {
5509 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005510 } else if (Tok.getString() == "mips1") {
5511 return parseSetFeature(Mips::FeatureMips1);
5512 } else if (Tok.getString() == "mips2") {
5513 return parseSetFeature(Mips::FeatureMips2);
5514 } else if (Tok.getString() == "mips3") {
5515 return parseSetFeature(Mips::FeatureMips3);
5516 } else if (Tok.getString() == "mips4") {
5517 return parseSetFeature(Mips::FeatureMips4);
5518 } else if (Tok.getString() == "mips5") {
5519 return parseSetFeature(Mips::FeatureMips5);
5520 } else if (Tok.getString() == "mips32") {
5521 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005522 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005523 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005524 } else if (Tok.getString() == "mips32r3") {
5525 return parseSetFeature(Mips::FeatureMips32r3);
5526 } else if (Tok.getString() == "mips32r5") {
5527 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005528 } else if (Tok.getString() == "mips32r6") {
5529 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005530 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005531 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005532 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005533 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005534 } else if (Tok.getString() == "mips64r3") {
5535 return parseSetFeature(Mips::FeatureMips64r3);
5536 } else if (Tok.getString() == "mips64r5") {
5537 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005538 } else if (Tok.getString() == "mips64r6") {
5539 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005540 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005541 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005542 } else if (Tok.getString() == "nodsp") {
5543 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005544 } else if (Tok.getString() == "msa") {
5545 return parseSetMsaDirective();
5546 } else if (Tok.getString() == "nomsa") {
5547 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005548 } else if (Tok.getString() == "softfloat") {
5549 return parseSetSoftFloatDirective();
5550 } else if (Tok.getString() == "hardfloat") {
5551 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005552 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005553 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005554 parseSetAssignment();
5555 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005556 }
Jack Carter07c818d2013-01-25 01:31:34 +00005557
Jack Carter0b744b32012-10-04 02:29:46 +00005558 return true;
5559}
5560
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005561/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005562/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005563bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005564 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005565 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5566 for (;;) {
5567 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005568 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005569 return true;
5570
5571 getParser().getStreamer().EmitValue(Value, Size);
5572
5573 if (getLexer().is(AsmToken::EndOfStatement))
5574 break;
5575
Jack Carter07c818d2013-01-25 01:31:34 +00005576 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005577 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005578 Parser.Lex();
5579 }
5580 }
5581
5582 Parser.Lex();
5583 return false;
5584}
5585
Vladimir Medic4c299852013-11-06 11:27:05 +00005586/// parseDirectiveGpWord
5587/// ::= .gpword local_sym
5588bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005589 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005590 const MCExpr *Value;
5591 // EmitGPRel32Value requires an expression, so we are using base class
5592 // method to evaluate the expression.
5593 if (getParser().parseExpression(Value))
5594 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005595 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005596
Vladimir Medice10c1122013-11-13 13:18:04 +00005597 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005598 return Error(getLexer().getLoc(),
5599 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005600 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005601 return false;
5602}
5603
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005604/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005605/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005606bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005607 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005608 const MCExpr *Value;
5609 // EmitGPRel64Value requires an expression, so we are using base class
5610 // method to evaluate the expression.
5611 if (getParser().parseExpression(Value))
5612 return true;
5613 getParser().getStreamer().EmitGPRel64Value(Value);
5614
5615 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005616 return Error(getLexer().getLoc(),
5617 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005618 Parser.Lex(); // Eat EndOfStatement token.
5619 return false;
5620}
5621
Jack Carter0cd3c192014-01-06 23:27:31 +00005622bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005623 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005624 // Get the option token.
5625 AsmToken Tok = Parser.getTok();
5626 // At the moment only identifiers are supported.
5627 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005628 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005629 Parser.eatToEndOfStatement();
5630 return false;
5631 }
5632
5633 StringRef Option = Tok.getIdentifier();
5634
5635 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005636 // MipsAsmParser needs to know if the current PIC mode changes.
5637 IsPicEnabled = false;
5638
Jack Carter0cd3c192014-01-06 23:27:31 +00005639 getTargetStreamer().emitDirectiveOptionPic0();
5640 Parser.Lex();
5641 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5642 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005643 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005644 Parser.eatToEndOfStatement();
5645 }
5646 return false;
5647 }
5648
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005649 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005650 // MipsAsmParser needs to know if the current PIC mode changes.
5651 IsPicEnabled = true;
5652
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005653 getTargetStreamer().emitDirectiveOptionPic2();
5654 Parser.Lex();
5655 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5656 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005657 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005658 Parser.eatToEndOfStatement();
5659 }
5660 return false;
5661 }
5662
Jack Carter0cd3c192014-01-06 23:27:31 +00005663 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005664 Warning(Parser.getTok().getLoc(),
5665 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005666 Parser.eatToEndOfStatement();
5667 return false;
5668}
5669
Toma Tabacu9ca50962015-04-16 09:53:47 +00005670/// parseInsnDirective
5671/// ::= .insn
5672bool MipsAsmParser::parseInsnDirective() {
5673 // If this is not the end of the statement, report an error.
5674 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5675 reportParseError("unexpected token, expected end of statement");
5676 return false;
5677 }
5678
5679 // The actual label marking happens in
5680 // MipsELFStreamer::createPendingLabelRelocs().
5681 getTargetStreamer().emitDirectiveInsn();
5682
5683 getParser().Lex(); // Eat EndOfStatement token.
5684 return false;
5685}
5686
Daniel Sanders7e527422014-07-10 13:38:23 +00005687/// parseDirectiveModule
5688/// ::= .module oddspreg
5689/// ::= .module nooddspreg
5690/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005691/// ::= .module softfloat
5692/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005693bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005694 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005695 MCAsmLexer &Lexer = getLexer();
5696 SMLoc L = Lexer.getLoc();
5697
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005698 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005699 // TODO : get a better message.
5700 reportParseError(".module directive must appear before any code");
5701 return false;
5702 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005703
Toma Tabacuc405c822015-01-23 10:40:19 +00005704 StringRef Option;
5705 if (Parser.parseIdentifier(Option)) {
5706 reportParseError("expected .module option identifier");
5707 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005708 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005709
Toma Tabacuc405c822015-01-23 10:40:19 +00005710 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005711 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005712
Toma Tabacu3c499582015-06-25 10:56:57 +00005713 // Synchronize the abiflags information with the FeatureBits information we
5714 // changed above.
5715 getTargetStreamer().updateABIInfo(*this);
5716
5717 // If printing assembly, use the recently updated abiflags information.
5718 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5719 // emitted at the end).
5720 getTargetStreamer().emitDirectiveModuleOddSPReg();
5721
Toma Tabacuc405c822015-01-23 10:40:19 +00005722 // If this is not the end of the statement, report an error.
5723 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5724 reportParseError("unexpected token, expected end of statement");
5725 return false;
5726 }
5727
5728 return false; // parseDirectiveModule has finished successfully.
5729 } else if (Option == "nooddspreg") {
5730 if (!isABI_O32()) {
5731 Error(L, "'.module nooddspreg' requires the O32 ABI");
5732 return false;
5733 }
5734
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005735 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005736
Toma Tabacu3c499582015-06-25 10:56:57 +00005737 // Synchronize the abiflags information with the FeatureBits information we
5738 // changed above.
5739 getTargetStreamer().updateABIInfo(*this);
5740
5741 // If printing assembly, use the recently updated abiflags information.
5742 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5743 // emitted at the end).
5744 getTargetStreamer().emitDirectiveModuleOddSPReg();
5745
Toma Tabacuc405c822015-01-23 10:40:19 +00005746 // If this is not the end of the statement, report an error.
5747 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5748 reportParseError("unexpected token, expected end of statement");
5749 return false;
5750 }
5751
5752 return false; // parseDirectiveModule has finished successfully.
5753 } else if (Option == "fp") {
5754 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005755 } else if (Option == "softfloat") {
5756 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5757
5758 // Synchronize the ABI Flags information with the FeatureBits information we
5759 // updated above.
5760 getTargetStreamer().updateABIInfo(*this);
5761
5762 // If printing assembly, use the recently updated ABI Flags information.
5763 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5764 // emitted later).
5765 getTargetStreamer().emitDirectiveModuleSoftFloat();
5766
5767 // If this is not the end of the statement, report an error.
5768 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5769 reportParseError("unexpected token, expected end of statement");
5770 return false;
5771 }
5772
5773 return false; // parseDirectiveModule has finished successfully.
5774 } else if (Option == "hardfloat") {
5775 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5776
5777 // Synchronize the ABI Flags information with the FeatureBits information we
5778 // updated above.
5779 getTargetStreamer().updateABIInfo(*this);
5780
5781 // If printing assembly, use the recently updated ABI Flags information.
5782 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5783 // emitted later).
5784 getTargetStreamer().emitDirectiveModuleHardFloat();
5785
5786 // If this is not the end of the statement, report an error.
5787 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5788 reportParseError("unexpected token, expected end of statement");
5789 return false;
5790 }
5791
5792 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005793 } else {
5794 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5795 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005796}
5797
5798/// parseDirectiveModuleFP
5799/// ::= =32
5800/// ::= =xx
5801/// ::= =64
5802bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005803 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005804 MCAsmLexer &Lexer = getLexer();
5805
5806 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005807 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005808 return false;
5809 }
5810 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005811
Daniel Sanders7e527422014-07-10 13:38:23 +00005812 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005813 if (!parseFpABIValue(FpABI, ".module"))
5814 return false;
5815
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005816 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005817 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005818 return false;
5819 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005820
Toma Tabacua64e5402015-06-25 12:44:38 +00005821 // Synchronize the abiflags information with the FeatureBits information we
5822 // changed above.
5823 getTargetStreamer().updateABIInfo(*this);
5824
5825 // If printing assembly, use the recently updated abiflags information.
5826 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5827 // emitted at the end).
5828 getTargetStreamer().emitDirectiveModuleFP();
5829
Daniel Sanders7e527422014-07-10 13:38:23 +00005830 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005831 return false;
5832}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005833
Daniel Sanders7e527422014-07-10 13:38:23 +00005834bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005835 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005836 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005837 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005838 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005839
5840 if (Lexer.is(AsmToken::Identifier)) {
5841 StringRef Value = Parser.getTok().getString();
5842 Parser.Lex();
5843
5844 if (Value != "xx") {
5845 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5846 return false;
5847 }
5848
5849 if (!isABI_O32()) {
5850 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5851 return false;
5852 }
5853
Daniel Sanders7e527422014-07-10 13:38:23 +00005854 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005855 if (ModuleLevelOptions) {
5856 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5857 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5858 } else {
5859 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5860 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5861 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005862 return true;
5863 }
5864
5865 if (Lexer.is(AsmToken::Integer)) {
5866 unsigned Value = Parser.getTok().getIntVal();
5867 Parser.Lex();
5868
5869 if (Value != 32 && Value != 64) {
5870 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5871 return false;
5872 }
5873
5874 if (Value == 32) {
5875 if (!isABI_O32()) {
5876 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5877 return false;
5878 }
5879
Daniel Sanders7e527422014-07-10 13:38:23 +00005880 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005881 if (ModuleLevelOptions) {
5882 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5883 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5884 } else {
5885 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5886 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5887 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005888 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005889 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005890 if (ModuleLevelOptions) {
5891 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5892 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5893 } else {
5894 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5895 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5896 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005897 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005898
Daniel Sanders7e527422014-07-10 13:38:23 +00005899 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005900 }
5901
5902 return false;
5903}
5904
Jack Carter0b744b32012-10-04 02:29:46 +00005905bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005906 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005907 StringRef IDVal = DirectiveID.getString();
5908
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005909 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005910 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005911 if (IDVal == ".cprestore")
5912 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005913 if (IDVal == ".dword") {
5914 parseDataDirective(8, DirectiveID.getLoc());
5915 return false;
5916 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005917 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005918 StringRef SymbolName;
5919
5920 if (Parser.parseIdentifier(SymbolName)) {
5921 reportParseError("expected identifier after .ent");
5922 return false;
5923 }
5924
5925 // There's an undocumented extension that allows an integer to
5926 // follow the name of the procedure which AFAICS is ignored by GAS.
5927 // Example: .ent foo,2
5928 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5929 if (getLexer().isNot(AsmToken::Comma)) {
5930 // Even though we accept this undocumented extension for compatibility
5931 // reasons, the additional integer argument does not actually change
5932 // the behaviour of the '.ent' directive, so we would like to discourage
5933 // its use. We do this by not referring to the extended version in
5934 // error messages which are not directly related to its use.
5935 reportParseError("unexpected token, expected end of statement");
5936 return false;
5937 }
5938 Parser.Lex(); // Eat the comma.
5939 const MCExpr *DummyNumber;
5940 int64_t DummyNumberVal;
5941 // If the user was explicitly trying to use the extended version,
5942 // we still give helpful extension-related error messages.
5943 if (Parser.parseExpression(DummyNumber)) {
5944 reportParseError("expected number after comma");
5945 return false;
5946 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005947 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005948 reportParseError("expected an absolute expression after comma");
5949 return false;
5950 }
5951 }
5952
5953 // If this is not the end of the statement, report an error.
5954 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5955 reportParseError("unexpected token, expected end of statement");
5956 return false;
5957 }
5958
Jim Grosbach6f482002015-05-18 18:43:14 +00005959 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005960
5961 getTargetStreamer().emitDirectiveEnt(*Sym);
5962 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005963 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005964 return false;
5965 }
5966
Jack Carter07c818d2013-01-25 01:31:34 +00005967 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005968 StringRef SymbolName;
5969
5970 if (Parser.parseIdentifier(SymbolName)) {
5971 reportParseError("expected identifier after .end");
5972 return false;
5973 }
5974
5975 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5976 reportParseError("unexpected token, expected end of statement");
5977 return false;
5978 }
5979
5980 if (CurrentFn == nullptr) {
5981 reportParseError(".end used without .ent");
5982 return false;
5983 }
5984
5985 if ((SymbolName != CurrentFn->getName())) {
5986 reportParseError(".end symbol does not match .ent symbol");
5987 return false;
5988 }
5989
5990 getTargetStreamer().emitDirectiveEnd(SymbolName);
5991 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005992 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005993 return false;
5994 }
5995
Jack Carter07c818d2013-01-25 01:31:34 +00005996 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005997 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5998 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005999 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006000 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6001 reportParseError("expected stack register");
6002 return false;
6003 }
6004
6005 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6006 if (!StackRegOpnd.isGPRAsmReg()) {
6007 reportParseError(StackRegOpnd.getStartLoc(),
6008 "expected general purpose register");
6009 return false;
6010 }
6011 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6012
6013 if (Parser.getTok().is(AsmToken::Comma))
6014 Parser.Lex();
6015 else {
6016 reportParseError("unexpected token, expected comma");
6017 return false;
6018 }
6019
6020 // Parse the frame size.
6021 const MCExpr *FrameSize;
6022 int64_t FrameSizeVal;
6023
6024 if (Parser.parseExpression(FrameSize)) {
6025 reportParseError("expected frame size value");
6026 return false;
6027 }
6028
Jim Grosbach13760bd2015-05-30 01:25:56 +00006029 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006030 reportParseError("frame size not an absolute expression");
6031 return false;
6032 }
6033
6034 if (Parser.getTok().is(AsmToken::Comma))
6035 Parser.Lex();
6036 else {
6037 reportParseError("unexpected token, expected comma");
6038 return false;
6039 }
6040
6041 // Parse the return register.
6042 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006043 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006044 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6045 reportParseError("expected return register");
6046 return false;
6047 }
6048
6049 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6050 if (!ReturnRegOpnd.isGPRAsmReg()) {
6051 reportParseError(ReturnRegOpnd.getStartLoc(),
6052 "expected general purpose register");
6053 return false;
6054 }
6055
6056 // If this is not the end of the statement, report an error.
6057 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6058 reportParseError("unexpected token, expected end of statement");
6059 return false;
6060 }
6061
6062 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6063 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006064 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006065 return false;
6066 }
6067
Jack Carter07c818d2013-01-25 01:31:34 +00006068 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00006069 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00006070 }
6071
Daniel Sandersd97a6342014-08-13 10:07:34 +00006072 if (IDVal == ".mask" || IDVal == ".fmask") {
6073 // .mask bitmask, frame_offset
6074 // bitmask: One bit for each register used.
6075 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6076 // first register is expected to be saved.
6077 // Examples:
6078 // .mask 0x80000000, -4
6079 // .fmask 0x80000000, -4
6080 //
Jack Carterbe332172012-09-07 00:48:02 +00006081
Daniel Sandersd97a6342014-08-13 10:07:34 +00006082 // Parse the bitmask
6083 const MCExpr *BitMask;
6084 int64_t BitMaskVal;
6085
6086 if (Parser.parseExpression(BitMask)) {
6087 reportParseError("expected bitmask value");
6088 return false;
6089 }
6090
Jim Grosbach13760bd2015-05-30 01:25:56 +00006091 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006092 reportParseError("bitmask not an absolute expression");
6093 return false;
6094 }
6095
6096 if (Parser.getTok().is(AsmToken::Comma))
6097 Parser.Lex();
6098 else {
6099 reportParseError("unexpected token, expected comma");
6100 return false;
6101 }
6102
6103 // Parse the frame_offset
6104 const MCExpr *FrameOffset;
6105 int64_t FrameOffsetVal;
6106
6107 if (Parser.parseExpression(FrameOffset)) {
6108 reportParseError("expected frame offset value");
6109 return false;
6110 }
6111
Jim Grosbach13760bd2015-05-30 01:25:56 +00006112 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006113 reportParseError("frame offset not an absolute expression");
6114 return false;
6115 }
6116
6117 // If this is not the end of the statement, report an error.
6118 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6119 reportParseError("unexpected token, expected end of statement");
6120 return false;
6121 }
6122
6123 if (IDVal == ".mask")
6124 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6125 else
6126 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006127 return false;
6128 }
6129
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006130 if (IDVal == ".nan")
6131 return parseDirectiveNaN();
6132
Jack Carter07c818d2013-01-25 01:31:34 +00006133 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006134 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006135 return false;
6136 }
6137
Rafael Espindolab59fb732014-03-28 18:50:26 +00006138 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006139 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006140 return false;
6141 }
6142
Jack Carter07c818d2013-01-25 01:31:34 +00006143 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006144 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006145 return false;
6146 }
6147
Jack Carter0cd3c192014-01-06 23:27:31 +00006148 if (IDVal == ".option")
6149 return parseDirectiveOption();
6150
6151 if (IDVal == ".abicalls") {
6152 getTargetStreamer().emitDirectiveAbiCalls();
6153 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006154 Error(Parser.getTok().getLoc(),
6155 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006156 // Clear line
6157 Parser.eatToEndOfStatement();
6158 }
6159 return false;
6160 }
6161
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006162 if (IDVal == ".cpsetup")
6163 return parseDirectiveCPSetup();
6164
Daniel Sandersf173dda2015-09-22 10:50:09 +00006165 if (IDVal == ".cpreturn")
6166 return parseDirectiveCPReturn();
6167
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006168 if (IDVal == ".module")
6169 return parseDirectiveModule();
6170
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006171 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
6172 return parseInternalDirectiveReallowModule();
6173
Toma Tabacu9ca50962015-04-16 09:53:47 +00006174 if (IDVal == ".insn")
6175 return parseInsnDirective();
6176
Rafael Espindola870c4e92012-01-11 03:56:41 +00006177 return true;
6178}
6179
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006180bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6181 // If this is not the end of the statement, report an error.
6182 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6183 reportParseError("unexpected token, expected end of statement");
6184 return false;
6185 }
6186
6187 getTargetStreamer().reallowModuleDirective();
6188
6189 getParser().Lex(); // Eat EndOfStatement token.
6190 return false;
6191}
6192
Rafael Espindola870c4e92012-01-11 03:56:41 +00006193extern "C" void LLVMInitializeMipsAsmParser() {
6194 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6195 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6196 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6197 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6198}
Jack Carterb4dbc172012-09-05 23:34:03 +00006199
6200#define GET_REGISTER_MATCHER
6201#define GET_MATCHER_IMPLEMENTATION
6202#include "MipsGenAsmMatcher.inc"