blob: 7e53e4b1cc883b432a2a02edda4161acd8e4fa4c [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Daniel Sandersa6994442015-08-18 12:33:54 +000014#include "MipsTargetObjectFile.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000017#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000022#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000023#include "llvm/MC/MCParser/MCAsmLexer.h"
24#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000025#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000026#include "llvm/MC/MCStreamer.h"
27#include "llvm/MC/MCSubtargetInfo.h"
28#include "llvm/MC/MCSymbol.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000029#include "llvm/Support/Debug.h"
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
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000236 bool expandAbs(MCInst &Inst, SMLoc IDLoc,
237 SmallVectorImpl<MCInst> &Instructions);
238
Toma Tabacu234482a2015-03-16 12:03:39 +0000239 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
240 SmallVectorImpl<MCInst> &Instructions);
241
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000242 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000243 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000244
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000245 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
246 SmallVectorImpl<MCInst> &Instructions);
247
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000248 bool reportParseError(Twine ErrorMsg);
249 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000250
Jack Carterb5cf5902013-04-17 00:18:04 +0000251 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000252 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000253
Vladimir Medic4c299852013-11-06 11:27:05 +0000254 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000255
256 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000257 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000258 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000259 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000260 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000261 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000262 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000263 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000264 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000265 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000266 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000267 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000268 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000269
270 bool parseSetAtDirective();
271 bool parseSetNoAtDirective();
272 bool parseSetMacroDirective();
273 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000274 bool parseSetMsaDirective();
275 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000276 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000277 bool parseSetReorderDirective();
278 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000279 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000280 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000281 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000282 bool parseSetOddSPRegDirective();
283 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000284 bool parseSetPopDirective();
285 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000286 bool parseSetSoftFloatDirective();
287 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000288
Jack Carterd76b2372013-03-21 21:44:16 +0000289 bool parseSetAssignment();
290
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000291 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000292 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000293 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000294 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000295 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000296 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
297 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000298
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000299 bool parseInternalDirectiveReallowModule();
300
Jack Carterdc1e35d2012-09-06 20:00:02 +0000301 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000302
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000303 bool eatComma(StringRef ErrorStr);
304
Jack Carter1ac53222013-02-20 23:11:17 +0000305 int matchCPURegisterName(StringRef Symbol);
306
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000307 int matchHWRegsRegisterName(StringRef Symbol);
308
Jack Carter873c7242013-01-12 01:03:14 +0000309 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000310
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000311 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000312
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000313 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000314
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000315 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000316
Jack Carter5dc8ac92013-09-25 23:50:44 +0000317 int matchMSA128RegisterName(StringRef Name);
318
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000319 int matchMSA128CtrlRegisterName(StringRef Name);
320
Jack Carterd0bd6422013-04-18 00:41:53 +0000321 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000322
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000323 unsigned getGPR(int RegNo);
324
Toma Tabacu89a712b2015-04-15 10:48:56 +0000325 /// Returns the internal register number for the current AT. Also checks if
326 /// the current AT is unavailable (set to $0) and gives an error if it is.
327 /// This should be used in pseudo-instruction expansions which need AT.
328 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000329
330 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000331 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000332
333 // Helper function that checks if the value of a vector index is within the
334 // boundaries of accepted values for each RegisterKind
335 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
336 bool validateMSAIndex(int Val, int RegKind);
337
Daniel Sandersf0df2212014-08-04 12:20:00 +0000338 // Selects a new architecture by updating the FeatureBits with the necessary
339 // info including implied dependencies.
340 // Internally, it clears all the feature bits related to *any* architecture
341 // and selects the new one using the ToggleFeature functionality of the
342 // MCSubtargetInfo object that handles implied dependencies. The reason we
343 // clear all the arch related bits manually is because ToggleFeature only
344 // clears the features that imply the feature being cleared and not the
345 // features implied by the feature being cleared. This is easier to see
346 // with an example:
347 // --------------------------------------------------
348 // | Feature | Implies |
349 // | -------------------------------------------------|
350 // | FeatureMips1 | None |
351 // | FeatureMips2 | FeatureMips1 |
352 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
353 // | FeatureMips4 | FeatureMips3 |
354 // | ... | |
355 // --------------------------------------------------
356 //
357 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
358 // FeatureMipsGP64 | FeatureMips1)
359 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
360 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000361 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000362 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000363 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
364 STI.setFeatureBits(FeatureBits);
365 setAvailableFeatures(
366 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000367 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000368 }
369
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000370 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000371 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000372 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000373 setAvailableFeatures(
374 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000375 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000376 }
377 }
378
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000379 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000380 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000381 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000382 setAvailableFeatures(
383 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000384 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000385 }
386 }
387
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000388 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
389 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000390 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000391 }
392
393 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
394 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000395 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000396 }
397
Rafael Espindola870c4e92012-01-11 03:56:41 +0000398public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000399 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000400 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000401#define GET_OPERAND_DIAGNOSTIC_TYPES
402#include "MipsGenAsmMatcher.inc"
403#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000404 };
405
Akira Hatanakab11ef082015-11-14 06:35:56 +0000406 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000407 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000408 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000409 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
410 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000411 MCAsmParserExtension::Initialize(parser);
412
Toma Tabacu11e14a92015-04-21 11:50:52 +0000413 parser.addAliasForDirective(".asciiz", ".asciz");
414
Jack Carterb4dbc172012-09-05 23:34:03 +0000415 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000416 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000417
Toma Tabacu9db22db2014-09-09 10:15:38 +0000418 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000419 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000420 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000421
Toma Tabacu9db22db2014-09-09 10:15:38 +0000422 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000423 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000424 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000425
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000426 getTargetStreamer().updateABIInfo(*this);
427
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000428 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000429 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000430
431 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000432
Daniel Sandersa6994442015-08-18 12:33:54 +0000433 IsPicEnabled =
434 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
435
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000436 IsCpRestoreSet = false;
437 CpRestoreOffset = -1;
438
Daniel Sanders50f17232015-09-15 16:17:27 +0000439 Triple TheTriple(sti.getTargetTriple());
440 if ((TheTriple.getArch() == Triple::mips) ||
441 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000442 IsLittleEndian = false;
443 else
444 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000445 }
446
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000447 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
448 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
449
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000450 bool isGP64bit() const {
451 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
452 }
453 bool isFP64bit() const {
454 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
455 }
Eric Christophera5762812015-01-26 17:33:46 +0000456 const MipsABIInfo &getABI() const { return ABI; }
457 bool isABI_N32() const { return ABI.IsN32(); }
458 bool isABI_N64() const { return ABI.IsN64(); }
459 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000460 bool isABI_FPXX() const {
461 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
462 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000463
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000464 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000465 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000466 }
467
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000468 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000469 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000470 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000471 bool hasMips1() const {
472 return getSTI().getFeatureBits()[Mips::FeatureMips1];
473 }
474 bool hasMips2() const {
475 return getSTI().getFeatureBits()[Mips::FeatureMips2];
476 }
477 bool hasMips3() const {
478 return getSTI().getFeatureBits()[Mips::FeatureMips3];
479 }
480 bool hasMips4() const {
481 return getSTI().getFeatureBits()[Mips::FeatureMips4];
482 }
483 bool hasMips5() const {
484 return getSTI().getFeatureBits()[Mips::FeatureMips5];
485 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000486 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000487 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000488 }
489 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000490 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000491 }
492 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000493 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000494 }
495 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000496 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 }
Daniel Sanders17793142015-02-18 16:24:50 +0000498 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000500 }
501 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000502 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000503 }
504 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000505 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000506 }
507 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000508 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000509 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000510 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000511 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000512 }
513 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000514 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000515 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000516
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000517 bool hasDSP() const {
518 return getSTI().getFeatureBits()[Mips::FeatureDSP];
519 }
520 bool hasDSPR2() const {
521 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
522 }
523 bool hasDSPR3() const {
524 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
525 }
526 bool hasMSA() const {
527 return getSTI().getFeatureBits()[Mips::FeatureMSA];
528 }
Kai Nackee0245392015-01-27 19:11:28 +0000529 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000530 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000531 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000532
Daniel Sandersa6994442015-08-18 12:33:54 +0000533 bool inPicMode() {
534 return IsPicEnabled;
535 }
536
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000537 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000538 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000539 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000540
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000541 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000542 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000543 }
544
Eric Christophere8ae3e32015-05-07 23:10:21 +0000545 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000546 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000547 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000548
Toma Tabacud9d344b2015-04-27 14:05:04 +0000549 /// Warn if RegIndex is the same as the current AT.
550 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000551
552 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000553
554 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000555};
556}
557
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000558namespace {
559
560/// MipsOperand - Instances of this class represent a parsed Mips machine
561/// instruction.
562class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000563public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000564 /// Broad categories of register classes
565 /// The exact class is finalized by the render method.
566 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000567 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000568 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000569 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000570 RegKind_FCC = 4, /// FCC
571 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
572 RegKind_MSACtrl = 16, /// MSA control registers
573 RegKind_COP2 = 32, /// COP2
574 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
575 /// context).
576 RegKind_CCR = 128, /// CCR
577 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000578 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000579 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000580 /// Potentially any (e.g. $1)
581 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
582 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000583 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000584 };
585
586private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000587 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000588 k_Immediate, /// An immediate (possibly involving symbol references)
589 k_Memory, /// Base + Offset Memory Address
590 k_PhysRegister, /// A physical register from the Mips namespace
591 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000592 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000593 k_RegList, /// A physical register list
594 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000595 } Kind;
596
David Blaikie960ea3f2014-06-08 16:18:35 +0000597public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000598 MipsOperand(KindTy K, MipsAsmParser &Parser)
599 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
600
David Blaikie960ea3f2014-06-08 16:18:35 +0000601private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000602 /// For diagnostics, and checking the assembler temporary
603 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000604
Eric Christopher8996c5d2013-03-15 00:42:55 +0000605 struct Token {
606 const char *Data;
607 unsigned Length;
608 };
609
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000610 struct PhysRegOp {
611 unsigned Num; /// Register Number
612 };
613
614 struct RegIdxOp {
615 unsigned Index; /// Index into the register class
616 RegKind Kind; /// Bitfield of the kinds it could possibly be
617 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000618 };
619
620 struct ImmOp {
621 const MCExpr *Val;
622 };
623
624 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000625 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000626 const MCExpr *Off;
627 };
628
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000629 struct RegListOp {
630 SmallVector<unsigned, 10> *List;
631 };
632
Jack Carterb4dbc172012-09-05 23:34:03 +0000633 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000634 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000635 struct PhysRegOp PhysReg;
636 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000637 struct ImmOp Imm;
638 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000639 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000640 };
641
642 SMLoc StartLoc, EndLoc;
643
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000644 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000645 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
646 const MCRegisterInfo *RegInfo,
647 SMLoc S, SMLoc E,
648 MipsAsmParser &Parser) {
649 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000650 Op->RegIdx.Index = Index;
651 Op->RegIdx.RegInfo = RegInfo;
652 Op->RegIdx.Kind = RegKind;
653 Op->StartLoc = S;
654 Op->EndLoc = E;
655 return Op;
656 }
657
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000658public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000659 /// Coerce the register to GPR32 and return the real register for the current
660 /// target.
661 unsigned getGPR32Reg() const {
662 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000663 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000664 unsigned ClassID = Mips::GPR32RegClassID;
665 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000666 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000667
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000668 /// Coerce the register to GPR32 and return the real register for the current
669 /// target.
670 unsigned getGPRMM16Reg() const {
671 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
672 unsigned ClassID = Mips::GPR32RegClassID;
673 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
674 }
675
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000676 /// Coerce the register to GPR64 and return the real register for the current
677 /// target.
678 unsigned getGPR64Reg() const {
679 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
680 unsigned ClassID = Mips::GPR64RegClassID;
681 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000682 }
683
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000684private:
685 /// Coerce the register to AFGR64 and return the real register for the current
686 /// target.
687 unsigned getAFGR64Reg() const {
688 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
689 if (RegIdx.Index % 2 != 0)
690 AsmParser.Warning(StartLoc, "Float register should be even.");
691 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
692 .getRegister(RegIdx.Index / 2);
693 }
694
695 /// Coerce the register to FGR64 and return the real register for the current
696 /// target.
697 unsigned getFGR64Reg() const {
698 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
699 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
700 .getRegister(RegIdx.Index);
701 }
702
703 /// Coerce the register to FGR32 and return the real register for the current
704 /// target.
705 unsigned getFGR32Reg() const {
706 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
707 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
708 .getRegister(RegIdx.Index);
709 }
710
711 /// Coerce the register to FGRH32 and return the real register for the current
712 /// target.
713 unsigned getFGRH32Reg() const {
714 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
715 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
716 .getRegister(RegIdx.Index);
717 }
718
719 /// Coerce the register to FCC and return the real register for the current
720 /// target.
721 unsigned getFCCReg() const {
722 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
723 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
724 .getRegister(RegIdx.Index);
725 }
726
727 /// Coerce the register to MSA128 and return the real register for the current
728 /// target.
729 unsigned getMSA128Reg() const {
730 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
731 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
732 // identical
733 unsigned ClassID = Mips::MSA128BRegClassID;
734 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
735 }
736
737 /// Coerce the register to MSACtrl and return the real register for the
738 /// current target.
739 unsigned getMSACtrlReg() const {
740 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
741 unsigned ClassID = Mips::MSACtrlRegClassID;
742 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
743 }
744
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000745 /// Coerce the register to COP0 and return the real register for the
746 /// current target.
747 unsigned getCOP0Reg() const {
748 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
749 unsigned ClassID = Mips::COP0RegClassID;
750 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
751 }
752
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000753 /// Coerce the register to COP2 and return the real register for the
754 /// current target.
755 unsigned getCOP2Reg() const {
756 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
757 unsigned ClassID = Mips::COP2RegClassID;
758 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
759 }
760
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000761 /// Coerce the register to COP3 and return the real register for the
762 /// current target.
763 unsigned getCOP3Reg() const {
764 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
765 unsigned ClassID = Mips::COP3RegClassID;
766 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
767 }
768
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000769 /// Coerce the register to ACC64DSP and return the real register for the
770 /// current target.
771 unsigned getACC64DSPReg() const {
772 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
773 unsigned ClassID = Mips::ACC64DSPRegClassID;
774 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
775 }
776
777 /// Coerce the register to HI32DSP and return the real register for the
778 /// current target.
779 unsigned getHI32DSPReg() const {
780 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
781 unsigned ClassID = Mips::HI32DSPRegClassID;
782 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
783 }
784
785 /// Coerce the register to LO32DSP and return the real register for the
786 /// current target.
787 unsigned getLO32DSPReg() const {
788 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
789 unsigned ClassID = Mips::LO32DSPRegClassID;
790 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
791 }
792
793 /// Coerce the register to CCR and return the real register for the
794 /// current target.
795 unsigned getCCRReg() const {
796 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
797 unsigned ClassID = Mips::CCRRegClassID;
798 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
799 }
800
801 /// Coerce the register to HWRegs and return the real register for the
802 /// current target.
803 unsigned getHWRegsReg() const {
804 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
805 unsigned ClassID = Mips::HWRegsRegClassID;
806 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
807 }
808
809public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000810 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000811 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000812 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000813 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000814 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000815 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000816 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000817 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000818 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000819
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000820 void addRegOperands(MCInst &Inst, unsigned N) const {
821 llvm_unreachable("Use a custom parser instead");
822 }
823
Daniel Sanders21bce302014-04-01 12:35:23 +0000824 /// Render the operand to an MCInst as a GPR32
825 /// Asserts if the wrong number of operands are requested, or the operand
826 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000827 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
828 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000829 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 }
831
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000832 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
833 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000834 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000835 }
836
Jozef Kolek1904fa22014-11-24 14:25:53 +0000837 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
838 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000839 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000840 }
841
Zoran Jovanovic41688672015-02-10 16:36:20 +0000842 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
843 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000844 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000845 }
846
Daniel Sanders21bce302014-04-01 12:35:23 +0000847 /// Render the operand to an MCInst as a GPR64
848 /// Asserts if the wrong number of operands are requested, or the operand
849 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
851 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000852 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000853 }
854
855 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
856 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000857 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000858 }
859
860 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
861 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000862 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000863 }
864
865 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
866 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000867 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000868 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000869 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000870 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
871 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000872 }
873
874 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
875 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000876 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000877 }
878
879 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
880 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000881 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000882 }
883
884 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
885 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000886 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000887 }
888
889 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
890 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000891 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000892 }
893
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000894 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
895 assert(N == 1 && "Invalid number of operands!");
896 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
897 }
898
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000899 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
900 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000901 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000902 }
903
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000904 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
905 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000906 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000907 }
908
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000909 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
910 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000911 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000912 }
913
914 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
915 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000916 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000917 }
918
919 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
920 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000921 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000922 }
923
924 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
925 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000926 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000927 }
928
929 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
930 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000931 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000932 }
933
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000934 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000935 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
936 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000937 uint64_t Imm = getConstantImm() - Offset;
938 Imm &= (1 << Bits) - 1;
939 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000940 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000941 Inst.addOperand(MCOperand::createImm(Imm));
942 }
943
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000944 template <unsigned Bits>
945 void addUImmOperands(MCInst &Inst, unsigned N) const {
946 if (isImm() && !isConstantImm()) {
947 addExpr(Inst, getImm());
948 return;
949 }
950 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
951 }
952
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000953 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000954 assert(N == 1 && "Invalid number of operands!");
955 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000956 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000957 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000958
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000959 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000960 assert(N == 2 && "Invalid number of operands!");
961
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000962 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
963 ? getMemBase()->getGPR64Reg()
964 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000965
966 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000967 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000968 }
969
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000970 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
971 assert(N == 2 && "Invalid number of operands!");
972
Jim Grosbache9119e42015-05-13 18:37:00 +0000973 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000974
975 const MCExpr *Expr = getMemOff();
976 addExpr(Inst, Expr);
977 }
978
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000979 void addRegListOperands(MCInst &Inst, unsigned N) const {
980 assert(N == 1 && "Invalid number of operands!");
981
982 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000983 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000984 }
985
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000986 void addRegPairOperands(MCInst &Inst, unsigned N) const {
987 assert(N == 2 && "Invalid number of operands!");
988 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000989 Inst.addOperand(MCOperand::createReg(RegNo++));
990 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000991 }
992
Zoran Jovanovic41688672015-02-10 16:36:20 +0000993 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
994 assert(N == 2 && "Invalid number of operands!");
995 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000996 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000997 }
998
Craig Topper56c590a2014-04-29 07:58:02 +0000999 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001000 // As a special case until we sort out the definition of div/divu, pretend
1001 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1002 if (isGPRAsmReg() && RegIdx.Index == 0)
1003 return true;
1004
1005 return Kind == k_PhysRegister;
1006 }
1007 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001008 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001009 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +00001010 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001011 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001012 bool isConstantImmz() const {
1013 return isConstantImm() && getConstantImm() == 0;
1014 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001015 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1016 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1017 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001018 template <unsigned Bits> bool isUImm() const {
1019 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1020 }
1021 template <unsigned Bits> bool isAnyImm() const {
1022 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1023 isUInt<Bits>(getConstantImm()))
1024 : isImm();
1025 }
Zlatko Buljan252cca52015-12-18 08:59:37 +00001026 template <unsigned Bits> bool isConstantSImm() const {
1027 return isConstantImm() && isInt<Bits>(getConstantImm());
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001028 }
Craig Topper56c590a2014-04-29 07:58:02 +00001029 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001030 // Note: It's not possible to pretend that other operand kinds are tokens.
1031 // The matcher emitter checks tokens first.
1032 return Kind == k_Token;
1033 }
Craig Topper56c590a2014-04-29 07:58:02 +00001034 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001035 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001036 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001037 }
1038 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001039 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1040 && getMemBase()->isGPRAsmReg();
1041 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001042 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
1043 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
1044 getMemBase()->isGPRAsmReg();
1045 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001046 bool isMemWithGRPMM16Base() const {
1047 return isMem() && getMemBase()->isMM16AsmReg();
1048 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001049 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1050 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1051 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1052 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001053 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1054 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1055 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1056 && (getMemBase()->getGPR32Reg() == Mips::SP);
1057 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001058 template <unsigned Bits, unsigned ShiftLeftAmount>
1059 bool isScaledUImm() const {
1060 return isConstantImm() &&
1061 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001062 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001063 bool isRegList16() const {
1064 if (!isRegList())
1065 return false;
1066
1067 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001068 if (Size < 2 || Size > 5)
1069 return false;
1070
1071 unsigned R0 = RegList.List->front();
1072 unsigned R1 = RegList.List->back();
1073 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1074 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001075 return false;
1076
1077 int PrevReg = *RegList.List->begin();
1078 for (int i = 1; i < Size - 1; i++) {
1079 int Reg = (*(RegList.List))[i];
1080 if ( Reg != PrevReg + 1)
1081 return false;
1082 PrevReg = Reg;
1083 }
1084
1085 return true;
1086 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001087 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001088 bool isLSAImm() const {
1089 if (!isConstantImm())
1090 return false;
1091 int64_t Val = getConstantImm();
1092 return 1 <= Val && Val <= 4;
1093 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001094 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001095 bool isMovePRegPair() const {
1096 if (Kind != k_RegList || RegList.List->size() != 2)
1097 return false;
1098
1099 unsigned R0 = RegList.List->front();
1100 unsigned R1 = RegList.List->back();
1101
1102 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1103 (R0 == Mips::A1 && R1 == Mips::A3) ||
1104 (R0 == Mips::A2 && R1 == Mips::A3) ||
1105 (R0 == Mips::A0 && R1 == Mips::S5) ||
1106 (R0 == Mips::A0 && R1 == Mips::S6) ||
1107 (R0 == Mips::A0 && R1 == Mips::A1) ||
1108 (R0 == Mips::A0 && R1 == Mips::A2) ||
1109 (R0 == Mips::A0 && R1 == Mips::A3))
1110 return true;
1111
1112 return false;
1113 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001114
1115 StringRef getToken() const {
1116 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001117 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001118 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001119 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001120
Craig Topper56c590a2014-04-29 07:58:02 +00001121 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001122 // As a special case until we sort out the definition of div/divu, pretend
1123 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1124 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1125 RegIdx.Kind & RegKind_GPR)
1126 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001127
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001128 assert(Kind == k_PhysRegister && "Invalid access!");
1129 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001130 }
1131
Jack Carterb4dbc172012-09-05 23:34:03 +00001132 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001133 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001134 return Imm.Val;
1135 }
1136
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001137 int64_t getConstantImm() const {
1138 const MCExpr *Val = getImm();
1139 return static_cast<const MCConstantExpr *>(Val)->getValue();
1140 }
1141
1142 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001143 assert((Kind == k_Memory) && "Invalid access!");
1144 return Mem.Base;
1145 }
1146
1147 const MCExpr *getMemOff() const {
1148 assert((Kind == k_Memory) && "Invalid access!");
1149 return Mem.Off;
1150 }
1151
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001152 int64_t getConstantMemOff() const {
1153 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1154 }
1155
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001156 const SmallVectorImpl<unsigned> &getRegList() const {
1157 assert((Kind == k_RegList) && "Invalid access!");
1158 return *(RegList.List);
1159 }
1160
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001161 unsigned getRegPair() const {
1162 assert((Kind == k_RegPair) && "Invalid access!");
1163 return RegIdx.Index;
1164 }
1165
David Blaikie960ea3f2014-06-08 16:18:35 +00001166 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1167 MipsAsmParser &Parser) {
1168 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001169 Op->Tok.Data = Str.data();
1170 Op->Tok.Length = Str.size();
1171 Op->StartLoc = S;
1172 Op->EndLoc = S;
1173 return Op;
1174 }
1175
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001176 /// Create a numeric register (e.g. $1). The exact register remains
1177 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001178 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001179 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001180 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001181 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001182 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001183 }
1184
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001185 /// Create a register that is definitely a GPR.
1186 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001187 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001188 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001189 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001190 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001191 }
1192
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001193 /// Create a register that is definitely a FGR.
1194 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001195 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001196 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001197 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001198 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1199 }
1200
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001201 /// Create a register that is definitely a HWReg.
1202 /// This is typically only used for named registers such as $hwr_cpunum.
1203 static std::unique_ptr<MipsOperand>
1204 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1205 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1206 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1207 }
1208
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001209 /// Create a register that is definitely an FCC.
1210 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001211 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001212 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001213 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001214 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1215 }
1216
1217 /// Create a register that is definitely an ACC.
1218 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001219 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001220 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001221 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001222 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1223 }
1224
1225 /// Create a register that is definitely an MSA128.
1226 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001227 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001228 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001229 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001230 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1231 }
1232
1233 /// Create a register that is definitely an MSACtrl.
1234 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001235 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001236 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001237 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001238 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1239 }
1240
David Blaikie960ea3f2014-06-08 16:18:35 +00001241 static std::unique_ptr<MipsOperand>
1242 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1243 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001244 Op->Imm.Val = Val;
1245 Op->StartLoc = S;
1246 Op->EndLoc = E;
1247 return Op;
1248 }
1249
David Blaikie960ea3f2014-06-08 16:18:35 +00001250 static std::unique_ptr<MipsOperand>
1251 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1252 SMLoc E, MipsAsmParser &Parser) {
1253 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1254 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001255 Op->Mem.Off = Off;
1256 Op->StartLoc = S;
1257 Op->EndLoc = E;
1258 return Op;
1259 }
1260
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001261 static std::unique_ptr<MipsOperand>
1262 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1263 MipsAsmParser &Parser) {
1264 assert (Regs.size() > 0 && "Empty list not allowed");
1265
1266 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001267 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001268 Op->StartLoc = StartLoc;
1269 Op->EndLoc = EndLoc;
1270 return Op;
1271 }
1272
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001273 static std::unique_ptr<MipsOperand>
1274 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1275 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1276 Op->RegIdx.Index = RegNo;
1277 Op->StartLoc = S;
1278 Op->EndLoc = E;
1279 return Op;
1280 }
1281
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001282 bool isGPRAsmReg() const {
1283 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001284 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001285 bool isMM16AsmReg() const {
1286 if (!(isRegIdx() && RegIdx.Kind))
1287 return false;
1288 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1289 || RegIdx.Index == 16 || RegIdx.Index == 17);
1290 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001291 bool isMM16AsmRegZero() const {
1292 if (!(isRegIdx() && RegIdx.Kind))
1293 return false;
1294 return (RegIdx.Index == 0 ||
1295 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1296 RegIdx.Index == 17);
1297 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001298 bool isMM16AsmRegMoveP() const {
1299 if (!(isRegIdx() && RegIdx.Kind))
1300 return false;
1301 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1302 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1303 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001304 bool isFGRAsmReg() const {
1305 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1306 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001307 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001308 bool isHWRegsAsmReg() const {
1309 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001310 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001311 bool isCCRAsmReg() const {
1312 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001313 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001314 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001315 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1316 return false;
1317 if (!AsmParser.hasEightFccRegisters())
1318 return RegIdx.Index == 0;
1319 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001320 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001321 bool isACCAsmReg() const {
1322 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001323 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001324 bool isCOP0AsmReg() const {
1325 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1326 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001327 bool isCOP2AsmReg() const {
1328 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001329 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001330 bool isCOP3AsmReg() const {
1331 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1332 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001333 bool isMSA128AsmReg() const {
1334 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001335 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001336 bool isMSACtrlAsmReg() const {
1337 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001338 }
1339
Jack Carterb4dbc172012-09-05 23:34:03 +00001340 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001341 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001342 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001343 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001344
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001345 virtual ~MipsOperand() {
1346 switch (Kind) {
1347 case k_Immediate:
1348 break;
1349 case k_Memory:
1350 delete Mem.Base;
1351 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001352 case k_RegList:
1353 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001354 case k_PhysRegister:
1355 case k_RegisterIndex:
1356 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001357 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001358 break;
1359 }
1360 }
1361
Craig Topper56c590a2014-04-29 07:58:02 +00001362 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001363 switch (Kind) {
1364 case k_Immediate:
1365 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001366 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001367 OS << ">";
1368 break;
1369 case k_Memory:
1370 OS << "Mem<";
1371 Mem.Base->print(OS);
1372 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001373 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001374 OS << ">";
1375 break;
1376 case k_PhysRegister:
1377 OS << "PhysReg<" << PhysReg.Num << ">";
1378 break;
1379 case k_RegisterIndex:
1380 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1381 break;
1382 case k_Token:
1383 OS << Tok.Data;
1384 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001385 case k_RegList:
1386 OS << "RegList< ";
1387 for (auto Reg : (*RegList.List))
1388 OS << Reg << " ";
1389 OS << ">";
1390 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001391 case k_RegPair:
1392 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1393 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001394 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001395 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001396}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001397} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001398
Jack Carter9e65aa32013-03-22 00:05:30 +00001399namespace llvm {
1400extern const MCInstrDesc MipsInsts[];
1401}
1402static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1403 return MipsInsts[Opcode];
1404}
1405
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001406static bool hasShortDelaySlot(unsigned Opcode) {
1407 switch (Opcode) {
1408 case Mips::JALS_MM:
1409 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001410 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001411 case Mips::BGEZALS_MM:
1412 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001413 return true;
1414 default:
1415 return false;
1416 }
1417}
1418
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001419static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1420 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1421 return &SRExpr->getSymbol();
1422 }
1423
1424 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1425 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1426 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1427
1428 if (LHSSym)
1429 return LHSSym;
1430
1431 if (RHSSym)
1432 return RHSSym;
1433
1434 return nullptr;
1435 }
1436
1437 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1438 return getSingleMCSymbol(UExpr->getSubExpr());
1439
1440 return nullptr;
1441}
1442
1443static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1444 if (isa<MCSymbolRefExpr>(Expr))
1445 return 1;
1446
1447 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1448 return countMCSymbolRefExpr(BExpr->getLHS()) +
1449 countMCSymbolRefExpr(BExpr->getRHS());
1450
1451 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1452 return countMCSymbolRefExpr(UExpr->getSubExpr());
1453
1454 return 0;
1455}
1456
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001457namespace {
1458void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1459 SmallVectorImpl<MCInst> &Instructions) {
1460 MCInst tmpInst;
1461 tmpInst.setOpcode(Opcode);
1462 tmpInst.addOperand(MCOperand::createReg(Reg0));
1463 tmpInst.addOperand(Op1);
1464 tmpInst.setLoc(IDLoc);
1465 Instructions.push_back(tmpInst);
1466}
1467
1468void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1469 SmallVectorImpl<MCInst> &Instructions) {
1470 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1471}
1472
1473void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1474 SmallVectorImpl<MCInst> &Instructions) {
1475 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1476}
1477
1478void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1479 SmallVectorImpl<MCInst> &Instructions) {
1480 MCInst tmpInst;
1481 tmpInst.setOpcode(Opcode);
1482 tmpInst.addOperand(MCOperand::createImm(Imm1));
1483 tmpInst.addOperand(MCOperand::createImm(Imm2));
1484 tmpInst.setLoc(IDLoc);
1485 Instructions.push_back(tmpInst);
1486}
1487
1488void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1489 SmallVectorImpl<MCInst> &Instructions) {
1490 MCInst tmpInst;
1491 tmpInst.setOpcode(Opcode);
1492 tmpInst.addOperand(MCOperand::createReg(Reg0));
1493 tmpInst.setLoc(IDLoc);
1494 Instructions.push_back(tmpInst);
1495}
1496
1497void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1498 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1499 MCInst tmpInst;
1500 tmpInst.setOpcode(Opcode);
1501 tmpInst.addOperand(MCOperand::createReg(Reg0));
1502 tmpInst.addOperand(MCOperand::createReg(Reg1));
1503 tmpInst.addOperand(Op2);
1504 tmpInst.setLoc(IDLoc);
1505 Instructions.push_back(tmpInst);
1506}
1507
1508void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1509 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1510 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1511 Instructions);
1512}
1513
1514void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1515 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1516 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1517 Instructions);
1518}
1519
1520void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1521 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1522 if (ShiftAmount >= 32) {
1523 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1524 Instructions);
1525 return;
1526 }
1527
1528 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1529}
1530} // end anonymous namespace.
1531
Jack Carter9e65aa32013-03-22 00:05:30 +00001532bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001533 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001534 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001535 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001536
Jack Carter9e65aa32013-03-22 00:05:30 +00001537 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001538
1539 if (MCID.isBranch() || MCID.isCall()) {
1540 const unsigned Opcode = Inst.getOpcode();
1541 MCOperand Offset;
1542
1543 switch (Opcode) {
1544 default:
1545 break;
Kai Nackee0245392015-01-27 19:11:28 +00001546 case Mips::BBIT0:
1547 case Mips::BBIT032:
1548 case Mips::BBIT1:
1549 case Mips::BBIT132:
1550 assert(hasCnMips() && "instruction only valid for octeon cpus");
1551 // Fall through
1552
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001553 case Mips::BEQ:
1554 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001555 case Mips::BEQ_MM:
1556 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001557 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001558 Offset = Inst.getOperand(2);
1559 if (!Offset.isImm())
1560 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001561 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001562 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001563 if (OffsetToAlignment(Offset.getImm(),
1564 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001565 return Error(IDLoc, "branch to misaligned address");
1566 break;
1567 case Mips::BGEZ:
1568 case Mips::BGTZ:
1569 case Mips::BLEZ:
1570 case Mips::BLTZ:
1571 case Mips::BGEZAL:
1572 case Mips::BLTZAL:
1573 case Mips::BC1F:
1574 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001575 case Mips::BGEZ_MM:
1576 case Mips::BGTZ_MM:
1577 case Mips::BLEZ_MM:
1578 case Mips::BLTZ_MM:
1579 case Mips::BGEZAL_MM:
1580 case Mips::BLTZAL_MM:
1581 case Mips::BC1F_MM:
1582 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001583 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001584 Offset = Inst.getOperand(1);
1585 if (!Offset.isImm())
1586 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001587 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001588 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001589 if (OffsetToAlignment(Offset.getImm(),
1590 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001591 return Error(IDLoc, "branch to misaligned address");
1592 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001593 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001594 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001595 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001596 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001597 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1598 Offset = Inst.getOperand(1);
1599 if (!Offset.isImm())
1600 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001601 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001602 return Error(IDLoc, "branch target out of range");
1603 if (OffsetToAlignment(Offset.getImm(), 2LL))
1604 return Error(IDLoc, "branch to misaligned address");
1605 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001606 }
1607 }
1608
Daniel Sandersa84989a2014-06-16 13:25:35 +00001609 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1610 // We still accept it but it is a normal nop.
1611 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1612 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1613 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1614 "nop instruction");
1615 }
1616
Kai Nackee0245392015-01-27 19:11:28 +00001617 if (hasCnMips()) {
1618 const unsigned Opcode = Inst.getOpcode();
1619 MCOperand Opnd;
1620 int Imm;
1621
1622 switch (Opcode) {
1623 default:
1624 break;
1625
1626 case Mips::BBIT0:
1627 case Mips::BBIT032:
1628 case Mips::BBIT1:
1629 case Mips::BBIT132:
1630 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1631 // The offset is handled above
1632 Opnd = Inst.getOperand(1);
1633 if (!Opnd.isImm())
1634 return Error(IDLoc, "expected immediate operand kind");
1635 Imm = Opnd.getImm();
1636 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1637 Opcode == Mips::BBIT1 ? 63 : 31))
1638 return Error(IDLoc, "immediate operand value out of range");
1639 if (Imm > 31) {
1640 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1641 : Mips::BBIT132);
1642 Inst.getOperand(1).setImm(Imm - 32);
1643 }
1644 break;
1645
Kai Nackee0245392015-01-27 19:11:28 +00001646 case Mips::SEQi:
1647 case Mips::SNEi:
1648 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1649 Opnd = Inst.getOperand(2);
1650 if (!Opnd.isImm())
1651 return Error(IDLoc, "expected immediate operand kind");
1652 Imm = Opnd.getImm();
1653 if (!isInt<10>(Imm))
1654 return Error(IDLoc, "immediate operand value out of range");
1655 break;
1656 }
1657 }
1658
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001659 // This expansion is not in a function called by tryExpandInstruction()
1660 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001661 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1662 inPicMode()) {
1663 warnIfNoMacro(IDLoc);
1664
1665 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1666
1667 // We can do this expansion if there's only 1 symbol in the argument
1668 // expression.
1669 if (countMCSymbolRefExpr(JalExpr) > 1)
1670 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1671
1672 // FIXME: This is checking the expression can be handled by the later stages
1673 // of the assembler. We ought to leave it to those later stages but
1674 // we can't do that until we stop evaluateRelocExpr() rewriting the
1675 // expressions into non-equivalent forms.
1676 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1677
1678 // FIXME: Add support for label+offset operands (currently causes an error).
1679 // FIXME: Add support for forward-declared local symbols.
1680 // FIXME: Add expansion for when the LargeGOT option is enabled.
1681 if (JalSym->isInSection() || JalSym->isTemporary()) {
1682 if (isABI_O32()) {
1683 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001684 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001685 // R_(MICRO)MIPS_GOT16 label
1686 // addiu $25, $25, 0
1687 // R_(MICRO)MIPS_LO16 label
1688 // jalr $25
1689 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1690 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1691
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001692 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1693 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1694 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1695 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001696 } else if (isABI_N32() || isABI_N64()) {
1697 // If it's a local symbol and the N32/N64 ABIs are being used,
1698 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001699 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001700 // R_(MICRO)MIPS_GOT_DISP label
1701 // jalr $25
1702 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1703
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001704 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1705 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001706 }
1707 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001708 // If it's an external/weak symbol, we expand to:
1709 // lw/ld $25, 0($gp)
1710 // R_(MICRO)MIPS_CALL16 label
1711 // jalr $25
1712 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001713
Daniel Sandersb7002032015-11-20 13:16:35 +00001714 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1715 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001716 }
1717
1718 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001719 if (IsCpRestoreSet && inMicroMipsMode())
1720 JalrInst.setOpcode(Mips::JALRS_MM);
1721 else
1722 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001723 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1724 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1725
1726 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1727 // This relocation is supposed to be an optimization hint for the linker
1728 // and is not necessary for correctness.
1729
1730 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001731 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001732 }
1733
Jack Carter9e65aa32013-03-22 00:05:30 +00001734 if (MCID.mayLoad() || MCID.mayStore()) {
1735 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001736 // reference or immediate we may have to expand instructions.
1737 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001738 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001739 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1740 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001741 MCOperand &Op = Inst.getOperand(i);
1742 if (Op.isImm()) {
1743 int MemOffset = Op.getImm();
1744 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001745 // Offset can't exceed 16bit value.
1746 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001747 return false;
1748 }
1749 } else if (Op.isExpr()) {
1750 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001751 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001752 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001753 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001754 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001755 // Expand symbol.
1756 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001757 return false;
1758 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001759 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001760 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001761 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001762 }
1763 }
1764 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001765 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001766 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001767
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001768 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001769 if (MCID.mayLoad()) {
1770 // Try to create 16-bit GP relative load instruction.
1771 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1772 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1773 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1774 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1775 MCOperand &Op = Inst.getOperand(i);
1776 if (Op.isImm()) {
1777 int MemOffset = Op.getImm();
1778 MCOperand &DstReg = Inst.getOperand(0);
1779 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001780 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001781 getContext().getRegisterInfo()->getRegClass(
1782 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001783 (BaseReg.getReg() == Mips::GP ||
1784 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001785
1786 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1787 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001788 return false;
1789 }
1790 }
1791 }
1792 } // for
1793 } // if load
1794
1795 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1796
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001797 MCOperand Opnd;
1798 int Imm;
1799
1800 switch (Inst.getOpcode()) {
1801 default:
1802 break;
1803 case Mips::ADDIUS5_MM:
1804 Opnd = Inst.getOperand(2);
1805 if (!Opnd.isImm())
1806 return Error(IDLoc, "expected immediate operand kind");
1807 Imm = Opnd.getImm();
1808 if (Imm < -8 || Imm > 7)
1809 return Error(IDLoc, "immediate operand value out of range");
1810 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001811 case Mips::ADDIUSP_MM:
1812 Opnd = Inst.getOperand(0);
1813 if (!Opnd.isImm())
1814 return Error(IDLoc, "expected immediate operand kind");
1815 Imm = Opnd.getImm();
1816 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1817 Imm % 4 != 0)
1818 return Error(IDLoc, "immediate operand value out of range");
1819 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001820 case Mips::SLL16_MM:
1821 case Mips::SRL16_MM:
1822 Opnd = Inst.getOperand(2);
1823 if (!Opnd.isImm())
1824 return Error(IDLoc, "expected immediate operand kind");
1825 Imm = Opnd.getImm();
1826 if (Imm < 1 || Imm > 8)
1827 return Error(IDLoc, "immediate operand value out of range");
1828 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001829 case Mips::LI16_MM:
1830 Opnd = Inst.getOperand(1);
1831 if (!Opnd.isImm())
1832 return Error(IDLoc, "expected immediate operand kind");
1833 Imm = Opnd.getImm();
1834 if (Imm < -1 || Imm > 126)
1835 return Error(IDLoc, "immediate operand value out of range");
1836 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001837 case Mips::ADDIUR2_MM:
1838 Opnd = Inst.getOperand(2);
1839 if (!Opnd.isImm())
1840 return Error(IDLoc, "expected immediate operand kind");
1841 Imm = Opnd.getImm();
1842 if (!(Imm == 1 || Imm == -1 ||
1843 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1844 return Error(IDLoc, "immediate operand value out of range");
1845 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001846 case Mips::ADDIUR1SP_MM:
1847 Opnd = Inst.getOperand(1);
1848 if (!Opnd.isImm())
1849 return Error(IDLoc, "expected immediate operand kind");
1850 Imm = Opnd.getImm();
1851 if (OffsetToAlignment(Imm, 4LL))
1852 return Error(IDLoc, "misaligned immediate operand value");
1853 if (Imm < 0 || Imm > 255)
1854 return Error(IDLoc, "immediate operand value out of range");
1855 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001856 case Mips::ANDI16_MM:
1857 Opnd = Inst.getOperand(2);
1858 if (!Opnd.isImm())
1859 return Error(IDLoc, "expected immediate operand kind");
1860 Imm = Opnd.getImm();
1861 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1862 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1863 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1864 return Error(IDLoc, "immediate operand value out of range");
1865 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001866 case Mips::LBU16_MM:
1867 Opnd = Inst.getOperand(2);
1868 if (!Opnd.isImm())
1869 return Error(IDLoc, "expected immediate operand kind");
1870 Imm = Opnd.getImm();
1871 if (Imm < -1 || Imm > 14)
1872 return Error(IDLoc, "immediate operand value out of range");
1873 break;
1874 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001875 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001876 Opnd = Inst.getOperand(2);
1877 if (!Opnd.isImm())
1878 return Error(IDLoc, "expected immediate operand kind");
1879 Imm = Opnd.getImm();
1880 if (Imm < 0 || Imm > 15)
1881 return Error(IDLoc, "immediate operand value out of range");
1882 break;
1883 case Mips::LHU16_MM:
1884 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001885 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001886 Opnd = Inst.getOperand(2);
1887 if (!Opnd.isImm())
1888 return Error(IDLoc, "expected immediate operand kind");
1889 Imm = Opnd.getImm();
1890 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1891 return Error(IDLoc, "immediate operand value out of range");
1892 break;
1893 case Mips::LW16_MM:
1894 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001895 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001896 Opnd = Inst.getOperand(2);
1897 if (!Opnd.isImm())
1898 return Error(IDLoc, "expected immediate operand kind");
1899 Imm = Opnd.getImm();
1900 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1901 return Error(IDLoc, "immediate operand value out of range");
1902 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001903 case Mips::ADDIUPC_MM:
1904 MCOperand Opnd = Inst.getOperand(1);
1905 if (!Opnd.isImm())
1906 return Error(IDLoc, "expected immediate operand kind");
1907 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001908 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001909 return Error(IDLoc, "immediate operand value out of range");
1910 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001911 }
1912 }
1913
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001914 MacroExpanderResultTy ExpandResult =
1915 tryExpandInstruction(Inst, IDLoc, Instructions);
1916 switch (ExpandResult) {
1917 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001918 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001919 break;
1920 case MER_Success:
1921 break;
1922 case MER_Fail:
1923 return true;
1924 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001925
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001926 // If this instruction has a delay slot and .set reorder is active,
1927 // emit a NOP after it.
1928 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1929 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1930
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001931 if ((Inst.getOpcode() == Mips::JalOneReg ||
1932 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1933 isPicAndNotNxxAbi()) {
1934 if (IsCpRestoreSet) {
1935 // We need a NOP between the JALR and the LW:
1936 // If .set reorder has been used, we've already emitted a NOP.
1937 // If .set noreorder has been used, we need to emit a NOP at this point.
1938 if (!AssemblerOptions.back()->isReorder())
1939 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1940
1941 // Load the $gp from the stack.
1942 SmallVector<MCInst, 3> LoadInsts;
1943 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1944 IDLoc, LoadInsts);
1945
1946 for (const MCInst &Inst : LoadInsts)
1947 Instructions.push_back(Inst);
1948
1949 } else
1950 Warning(IDLoc, "no .cprestore used in PIC mode");
1951 }
1952
Jack Carter9e65aa32013-03-22 00:05:30 +00001953 return false;
1954}
1955
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001956MipsAsmParser::MacroExpanderResultTy
1957MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1958 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001959 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001960 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001961 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001962 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001963 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1964 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001965 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001966 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1967 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001968 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001969 case Mips::LoadAddrImm64:
1970 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1971 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1972 "expected immediate operand kind");
1973
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001974 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1975 Inst.getOperand(1),
1976 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1977 Instructions)
1978 ? MER_Fail
1979 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001980 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001981 case Mips::LoadAddrReg64:
1982 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1983 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1984 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1985 "expected immediate operand kind");
1986
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001987 return expandLoadAddress(Inst.getOperand(0).getReg(),
1988 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1989 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
1990 Instructions)
1991 ? MER_Fail
1992 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001993 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001994 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001995 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
1996 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001997 case Mips::SWM_MM:
1998 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001999 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
2000 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002001 case Mips::JalOneReg:
2002 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002003 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
2004 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002005 case Mips::BneImm:
2006 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002007 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002008 case Mips::BLT:
2009 case Mips::BLE:
2010 case Mips::BGE:
2011 case Mips::BGT:
2012 case Mips::BLTU:
2013 case Mips::BLEU:
2014 case Mips::BGEU:
2015 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002016 case Mips::BLTL:
2017 case Mips::BLEL:
2018 case Mips::BGEL:
2019 case Mips::BGTL:
2020 case Mips::BLTUL:
2021 case Mips::BLEUL:
2022 case Mips::BGEUL:
2023 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002024 case Mips::BLTImmMacro:
2025 case Mips::BLEImmMacro:
2026 case Mips::BGEImmMacro:
2027 case Mips::BGTImmMacro:
2028 case Mips::BLTUImmMacro:
2029 case Mips::BLEUImmMacro:
2030 case Mips::BGEUImmMacro:
2031 case Mips::BGTUImmMacro:
2032 case Mips::BLTLImmMacro:
2033 case Mips::BLELImmMacro:
2034 case Mips::BGELImmMacro:
2035 case Mips::BGTLImmMacro:
2036 case Mips::BLTULImmMacro:
2037 case Mips::BLEULImmMacro:
2038 case Mips::BGEULImmMacro:
2039 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002040 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2041 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002042 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002043 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2044 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002045 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002046 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2047 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002048 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002049 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2050 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002051 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002052 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2053 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002054 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002055 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002056 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002057 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002058 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002059 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2060 case Mips::NORImm:
2061 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2062 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002063 case Mips::ADDi:
2064 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002065 case Mips::SLTi:
2066 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002067 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2068 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2069 int64_t ImmValue = Inst.getOperand(2).getImm();
2070 if (isInt<16>(ImmValue))
2071 return MER_NotAMacro;
2072 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2073 : MER_Success;
2074 }
2075 return MER_NotAMacro;
2076 case Mips::ANDi:
2077 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002078 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002079 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2080 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2081 int64_t ImmValue = Inst.getOperand(2).getImm();
2082 if (isUInt<16>(ImmValue))
2083 return MER_NotAMacro;
2084 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2085 : MER_Success;
2086 }
2087 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002088 case Mips::ROL:
2089 case Mips::ROR:
2090 return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail
2091 : MER_Success;
2092 case Mips::ROLImm:
2093 case Mips::RORImm:
2094 return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2095 : MER_Success;
2096 case Mips::DROL:
2097 case Mips::DROR:
2098 return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail
2099 : MER_Success;
2100 case Mips::DROLImm:
2101 case Mips::DRORImm:
2102 return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2103 : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002104 case Mips::ABSMacro:
2105 return expandAbs(Inst, IDLoc, Instructions) ? MER_Fail
2106 : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002107 }
Jack Carter30a59822012-10-04 04:03:53 +00002108}
Jack Carter92995f12012-10-06 00:53:28 +00002109
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002110bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2111 SmallVectorImpl<MCInst> &Instructions) {
2112 // Create a JALR instruction which is going to replace the pseudo-JAL.
2113 MCInst JalrInst;
2114 JalrInst.setLoc(IDLoc);
2115 const MCOperand FirstRegOp = Inst.getOperand(0);
2116 const unsigned Opcode = Inst.getOpcode();
2117
2118 if (Opcode == Mips::JalOneReg) {
2119 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002120 if (IsCpRestoreSet && inMicroMipsMode()) {
2121 JalrInst.setOpcode(Mips::JALRS16_MM);
2122 JalrInst.addOperand(FirstRegOp);
2123 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002124 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002125 JalrInst.addOperand(FirstRegOp);
2126 } else {
2127 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002128 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002129 JalrInst.addOperand(FirstRegOp);
2130 }
2131 } else if (Opcode == Mips::JalTwoReg) {
2132 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002133 if (IsCpRestoreSet && inMicroMipsMode())
2134 JalrInst.setOpcode(Mips::JALRS_MM);
2135 else
2136 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002137 JalrInst.addOperand(FirstRegOp);
2138 const MCOperand SecondRegOp = Inst.getOperand(1);
2139 JalrInst.addOperand(SecondRegOp);
2140 }
2141 Instructions.push_back(JalrInst);
2142
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002143 // If .set reorder is active and branch instruction has a delay slot,
2144 // emit a NOP after it.
2145 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2146 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002147 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002148 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002149
2150 return false;
2151}
2152
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002153/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002154template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002155 unsigned BitNum = findFirstSet(x);
2156
2157 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2158}
2159
2160/// Load (or add) an immediate into a register.
2161///
2162/// @param ImmValue The immediate to load.
2163/// @param DstReg The register that will hold the immediate.
2164/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2165/// for a simple initialization.
2166/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2167/// @param IsAddress True if the immediate represents an address. False if it
2168/// is an integer.
2169/// @param IDLoc Location of the immediate in the source file.
2170/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002171bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002172 unsigned SrcReg, bool Is32BitImm,
2173 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002174 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002175 if (!Is32BitImm && !isGP64bit()) {
2176 Error(IDLoc, "instruction requires a 64-bit architecture");
2177 return true;
2178 }
2179
Daniel Sanders03f9c012015-07-14 12:24:22 +00002180 if (Is32BitImm) {
2181 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2182 // Sign extend up to 64-bit so that the predicates match the hardware
2183 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2184 // true.
2185 ImmValue = SignExtend64<32>(ImmValue);
2186 } else {
2187 Error(IDLoc, "instruction requires a 32-bit immediate");
2188 return true;
2189 }
2190 }
2191
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002192 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2193 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2194
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002195 bool UseSrcReg = false;
2196 if (SrcReg != Mips::NoRegister)
2197 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002198
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002199 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002200 if (UseSrcReg &&
2201 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002202 // At this point we need AT to perform the expansions and we exit if it is
2203 // not available.
2204 unsigned ATReg = getATReg(IDLoc);
2205 if (!ATReg)
2206 return true;
2207 TmpReg = ATReg;
2208 }
2209
Daniel Sanders03f9c012015-07-14 12:24:22 +00002210 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002211 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002212 SrcReg = ZeroReg;
2213
2214 // This doesn't quite follow the usual ABI expectations for N32 but matches
2215 // traditional assembler behaviour. N32 would normally use addiu for both
2216 // integers and addresses.
2217 if (IsAddress && !Is32BitImm) {
2218 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2219 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002220 }
2221
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002222 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2223 return false;
2224 }
2225
2226 if (isUInt<16>(ImmValue)) {
2227 unsigned TmpReg = DstReg;
2228 if (SrcReg == DstReg) {
2229 TmpReg = getATReg(IDLoc);
2230 if (!TmpReg)
2231 return true;
2232 }
2233
2234 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002235 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002236 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2237 return false;
2238 }
2239
2240 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002241 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002242
Toma Tabacu79588102015-04-29 10:19:56 +00002243 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2244 uint16_t Bits15To0 = ImmValue & 0xffff;
2245
Toma Tabacua3d056f2015-05-15 09:42:11 +00002246 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002247 // Traditional behaviour seems to special case this particular value. It's
2248 // not clear why other masks are handled differently.
2249 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002250 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002251 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2252 if (UseSrcReg)
2253 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2254 return false;
2255 }
2256
2257 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002258 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002259 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002260 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002261 if (Bits15To0)
2262 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2263 if (UseSrcReg)
2264 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2265 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002266 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002267
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002268 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2269 if (Bits15To0)
2270 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002271 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002272 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2273 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002274 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002275
2276 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2277 if (Is32BitImm) {
2278 Error(IDLoc, "instruction requires a 32-bit immediate");
2279 return true;
2280 }
2281
2282 // Traditionally, these immediates are shifted as little as possible and as
2283 // such we align the most significant bit to bit 15 of our temporary.
2284 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2285 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2286 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2287 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2288 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2289 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2290
2291 if (UseSrcReg)
2292 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2293
2294 return false;
2295 }
2296
2297 warnIfNoMacro(IDLoc);
2298
2299 // The remaining case is packed with a sequence of dsll and ori with zeros
2300 // being omitted and any neighbouring dsll's being coalesced.
2301 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2302
2303 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2304 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2305 IDLoc, Instructions))
2306 return false;
2307
2308 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2309 // skip it and defer the shift to the next chunk.
2310 unsigned ShiftCarriedForwards = 16;
2311 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2312 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2313
2314 if (ImmChunk != 0) {
2315 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2316 Instructions);
2317 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2318 ShiftCarriedForwards = 0;
2319 }
2320
2321 ShiftCarriedForwards += 16;
2322 }
2323 ShiftCarriedForwards -= 16;
2324
2325 // Finish any remaining shifts left by trailing zeros.
2326 if (ShiftCarriedForwards)
2327 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2328 Instructions);
2329
2330 if (UseSrcReg)
2331 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2332
Matheus Almeida3813d572014-06-19 14:39:14 +00002333 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002334}
Jack Carter92995f12012-10-06 00:53:28 +00002335
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002336bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2337 SmallVectorImpl<MCInst> &Instructions) {
2338 const MCOperand &ImmOp = Inst.getOperand(1);
2339 assert(ImmOp.isImm() && "expected immediate operand kind");
2340 const MCOperand &DstRegOp = Inst.getOperand(0);
2341 assert(DstRegOp.isReg() && "expected register operand kind");
2342
2343 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002344 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002345 return true;
2346
2347 return false;
2348}
2349
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002350bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2351 const MCOperand &Offset,
2352 bool Is32BitAddress, SMLoc IDLoc,
2353 SmallVectorImpl<MCInst> &Instructions) {
2354 // la can't produce a usable address when addresses are 64-bit.
2355 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2356 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2357 // We currently can't do this because we depend on the equality
2358 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2359 Error(IDLoc, "la used to load 64-bit address");
2360 // Continue as if we had 'dla' instead.
2361 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002362 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002363
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002364 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002365 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002366 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002367 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002368 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002369
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002370 if (!Offset.isImm())
2371 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2372 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002373
Scott Egerton24557012016-01-21 15:11:01 +00002374 if (!ABI.ArePtrs64bit()) {
2375 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2376 Is32BitAddress = true;
2377 }
2378
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002379 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2380 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002381}
2382
Toma Tabacuf712ede2015-06-17 14:31:51 +00002383bool MipsAsmParser::loadAndAddSymbolAddress(
2384 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2385 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002386 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002387
Daniel Sandersd5a89412015-10-05 13:19:29 +00002388 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2389 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2390 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2391 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2392 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002393
Toma Tabacufb9d1252015-06-22 12:08:39 +00002394 bool UseSrcReg = SrcReg != Mips::NoRegister;
2395
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002396 // This is the 64-bit symbol address expansion.
2397 if (ABI.ArePtrs64bit() && isGP64bit()) {
2398 // We always need AT for the 64-bit expansion.
2399 // If it is not available we exit.
2400 unsigned ATReg = getATReg(IDLoc);
2401 if (!ATReg)
2402 return true;
2403
Daniel Sandersd5a89412015-10-05 13:19:29 +00002404 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2405 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2406 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2407 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002408
Scott Egerton24557012016-01-21 15:11:01 +00002409 if (UseSrcReg &&
2410 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2411 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002412 // If $rs is the same as $rd:
2413 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2414 // daddiu $at, $at, %higher(sym)
2415 // dsll $at, $at, 16
2416 // daddiu $at, $at, %hi(sym)
2417 // dsll $at, $at, 16
2418 // daddiu $at, $at, %lo(sym)
2419 // daddu $rd, $at, $rd
2420 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2421 Instructions);
2422 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2423 IDLoc, Instructions);
2424 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2425 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2426 Instructions);
2427 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2428 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2429 Instructions);
2430 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2431
2432 return false;
2433 }
2434
2435 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2436 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2437 // lui $at, %hi(sym)
2438 // daddiu $rd, $rd, %higher(sym)
2439 // daddiu $at, $at, %lo(sym)
2440 // dsll32 $rd, $rd, 0
2441 // daddu $rd, $rd, $at
2442 // (daddu $rd, $rd, $rs)
2443 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2444 Instructions);
2445 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2446 Instructions);
2447 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2448 IDLoc, Instructions);
2449 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2450 Instructions);
2451 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2452 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2453 if (UseSrcReg)
2454 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2455
2456 return false;
2457 }
2458
2459 // And now, the 32-bit symbol address expansion:
2460 // If $rs is the same as $rd:
2461 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2462 // ori $at, $at, %lo(sym)
2463 // addu $rd, $at, $rd
2464 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2465 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2466 // ori $rd, $rd, %lo(sym)
2467 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002468 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002469 if (UseSrcReg &&
2470 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002471 // If $rs is the same as $rd, we need to use AT.
2472 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002473 unsigned ATReg = getATReg(IDLoc);
2474 if (!ATReg)
2475 return true;
2476 TmpReg = ATReg;
2477 }
2478
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002479 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2480 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2481 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002482
Toma Tabacufb9d1252015-06-22 12:08:39 +00002483 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002484 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2485 else
Scott Egerton24557012016-01-21 15:11:01 +00002486 assert(
2487 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002488
Toma Tabacu674825c2015-06-16 12:16:24 +00002489 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002490}
2491
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002492bool MipsAsmParser::expandUncondBranchMMPseudo(
2493 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002494 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2495 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002496
2497 MCOperand Offset = Inst.getOperand(0);
2498 if (Offset.isExpr()) {
2499 Inst.clear();
2500 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002501 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2502 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2503 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002504 } else {
2505 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002506 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002507 // If offset fits into 11 bits then this instruction becomes microMIPS
2508 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002509 if (inMicroMipsMode())
2510 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002511 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002512 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002513 Error(IDLoc, "branch target out of range");
2514 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2515 Error(IDLoc, "branch to misaligned address");
2516 Inst.clear();
2517 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002518 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2519 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2520 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002521 }
2522 }
2523 Instructions.push_back(Inst);
2524
Zoran Jovanovicada70912015-09-07 11:56:37 +00002525 // If .set reorder is active and branch instruction has a delay slot,
2526 // emit a NOP after it.
2527 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2528 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002529 createNop(true, IDLoc, Instructions);
2530
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002531 return false;
2532}
2533
Toma Tabacue1e460d2015-06-11 10:36:10 +00002534bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2535 SmallVectorImpl<MCInst> &Instructions) {
2536 const MCOperand &DstRegOp = Inst.getOperand(0);
2537 assert(DstRegOp.isReg() && "expected register operand kind");
2538
2539 const MCOperand &ImmOp = Inst.getOperand(1);
2540 assert(ImmOp.isImm() && "expected immediate operand kind");
2541
2542 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2543 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2544
2545 unsigned OpCode = 0;
2546 switch(Inst.getOpcode()) {
2547 case Mips::BneImm:
2548 OpCode = Mips::BNE;
2549 break;
2550 case Mips::BeqImm:
2551 OpCode = Mips::BEQ;
2552 break;
2553 default:
2554 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2555 break;
2556 }
2557
2558 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002559 if (ImmValue == 0)
2560 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2561 Instructions);
2562 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002563 warnIfNoMacro(IDLoc);
2564
2565 unsigned ATReg = getATReg(IDLoc);
2566 if (!ATReg)
2567 return true;
2568
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002569 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2570 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002571 return true;
2572
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002573 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002574 }
2575 return false;
2576}
2577
Jack Carter9e65aa32013-03-22 00:05:30 +00002578void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002579 SmallVectorImpl<MCInst> &Instructions,
2580 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002581 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002582 const MCExpr *ExprOffset;
2583 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002584 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002585 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2586 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002587 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002588 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2589 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002590 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002591 if (isImmOpnd) {
2592 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2593 ImmOffset = Inst.getOperand(2).getImm();
2594 LoOffset = ImmOffset & 0x0000ffff;
2595 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002596 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002597 if (LoOffset & 0x8000)
2598 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002599 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002600 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002601 // These are some of the types of expansions we perform here:
2602 // 1) lw $8, sym => lui $8, %hi(sym)
2603 // lw $8, %lo(sym)($8)
2604 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2605 // add $8, $8, $9
2606 // lw $8, %lo(offset)($9)
2607 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2608 // add $at, $at, $8
2609 // lw $8, %lo(offset)($at)
2610 // 4) sw $8, sym => lui $at, %hi(sym)
2611 // sw $8, %lo(sym)($at)
2612 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2613 // add $at, $at, $8
2614 // sw $8, %lo(offset)($at)
2615 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2616 // ldc1 $f0, %lo(sym)($at)
2617 //
2618 // For load instructions we can use the destination register as a temporary
2619 // if base and dst are different (examples 1 and 2) and if the base register
2620 // is general purpose otherwise we must use $at (example 6) and error if it's
2621 // not available. For stores we must use $at (examples 4 and 5) because we
2622 // must not clobber the source register setting up the offset.
2623 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2624 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2625 unsigned RegClassIDOp0 =
2626 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2627 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2628 (RegClassIDOp0 == Mips::GPR64RegClassID);
2629 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002630 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002631 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002632 // At this point we need AT to perform the expansions and we exit if it is
2633 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002634 TmpRegNum = getATReg(IDLoc);
2635 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002636 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002637 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002638
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002639 emitRX(Mips::LUi, TmpRegNum,
2640 isImmOpnd ? MCOperand::createImm(HiOffset)
2641 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2642 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002643 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002644 if (BaseRegNum != Mips::ZERO)
2645 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002646 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002647 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002648 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2649 isImmOpnd
2650 ? MCOperand::createImm(LoOffset)
2651 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2652 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002653}
2654
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002655bool
2656MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2657 SmallVectorImpl<MCInst> &Instructions) {
2658 unsigned OpNum = Inst.getNumOperands();
2659 unsigned Opcode = Inst.getOpcode();
2660 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2661
2662 assert (Inst.getOperand(OpNum - 1).isImm() &&
2663 Inst.getOperand(OpNum - 2).isReg() &&
2664 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2665
2666 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2667 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002668 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2669 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2670 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2671 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002672 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002673 if (inMicroMipsMode() && hasMips32r6())
2674 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2675 else
2676 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2677 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002678
2679 Inst.setOpcode(NewOpcode);
2680 Instructions.push_back(Inst);
2681 return false;
2682}
2683
Toma Tabacu1a108322015-06-17 13:20:24 +00002684bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2685 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002686 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002687 unsigned PseudoOpcode = Inst.getOpcode();
2688 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002689 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002690 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2691
2692 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002693 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002694
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002695 unsigned TrgReg;
2696 if (TrgOp.isReg())
2697 TrgReg = TrgOp.getReg();
2698 else if (TrgOp.isImm()) {
2699 warnIfNoMacro(IDLoc);
2700 EmittedNoMacroWarning = true;
2701
2702 TrgReg = getATReg(IDLoc);
2703 if (!TrgReg)
2704 return true;
2705
2706 switch(PseudoOpcode) {
2707 default:
2708 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2709 case Mips::BLTImmMacro:
2710 PseudoOpcode = Mips::BLT;
2711 break;
2712 case Mips::BLEImmMacro:
2713 PseudoOpcode = Mips::BLE;
2714 break;
2715 case Mips::BGEImmMacro:
2716 PseudoOpcode = Mips::BGE;
2717 break;
2718 case Mips::BGTImmMacro:
2719 PseudoOpcode = Mips::BGT;
2720 break;
2721 case Mips::BLTUImmMacro:
2722 PseudoOpcode = Mips::BLTU;
2723 break;
2724 case Mips::BLEUImmMacro:
2725 PseudoOpcode = Mips::BLEU;
2726 break;
2727 case Mips::BGEUImmMacro:
2728 PseudoOpcode = Mips::BGEU;
2729 break;
2730 case Mips::BGTUImmMacro:
2731 PseudoOpcode = Mips::BGTU;
2732 break;
2733 case Mips::BLTLImmMacro:
2734 PseudoOpcode = Mips::BLTL;
2735 break;
2736 case Mips::BLELImmMacro:
2737 PseudoOpcode = Mips::BLEL;
2738 break;
2739 case Mips::BGELImmMacro:
2740 PseudoOpcode = Mips::BGEL;
2741 break;
2742 case Mips::BGTLImmMacro:
2743 PseudoOpcode = Mips::BGTL;
2744 break;
2745 case Mips::BLTULImmMacro:
2746 PseudoOpcode = Mips::BLTUL;
2747 break;
2748 case Mips::BLEULImmMacro:
2749 PseudoOpcode = Mips::BLEUL;
2750 break;
2751 case Mips::BGEULImmMacro:
2752 PseudoOpcode = Mips::BGEUL;
2753 break;
2754 case Mips::BGTULImmMacro:
2755 PseudoOpcode = Mips::BGTUL;
2756 break;
2757 }
2758
2759 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2760 false, IDLoc, Instructions))
2761 return true;
2762 }
2763
Toma Tabacu1a108322015-06-17 13:20:24 +00002764 switch (PseudoOpcode) {
2765 case Mips::BLT:
2766 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002767 case Mips::BLTL:
2768 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002769 AcceptsEquality = false;
2770 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002771 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2772 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002773 ZeroSrcOpcode = Mips::BGTZ;
2774 ZeroTrgOpcode = Mips::BLTZ;
2775 break;
2776 case Mips::BLE:
2777 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002778 case Mips::BLEL:
2779 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002780 AcceptsEquality = true;
2781 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002782 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2783 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002784 ZeroSrcOpcode = Mips::BGEZ;
2785 ZeroTrgOpcode = Mips::BLEZ;
2786 break;
2787 case Mips::BGE:
2788 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002789 case Mips::BGEL:
2790 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002791 AcceptsEquality = true;
2792 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002793 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2794 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002795 ZeroSrcOpcode = Mips::BLEZ;
2796 ZeroTrgOpcode = Mips::BGEZ;
2797 break;
2798 case Mips::BGT:
2799 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002800 case Mips::BGTL:
2801 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002802 AcceptsEquality = false;
2803 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002804 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2805 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002806 ZeroSrcOpcode = Mips::BLTZ;
2807 ZeroTrgOpcode = Mips::BGTZ;
2808 break;
2809 default:
2810 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2811 }
2812
Toma Tabacu1a108322015-06-17 13:20:24 +00002813 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2814 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2815 if (IsSrcRegZero && IsTrgRegZero) {
2816 // FIXME: All of these Opcode-specific if's are needed for compatibility
2817 // with GAS' behaviour. However, they may not generate the most efficient
2818 // code in some circumstances.
2819 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002820 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2821 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002822 return false;
2823 }
2824 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002825 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2826 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002827 Warning(IDLoc, "branch is always taken");
2828 return false;
2829 }
2830 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002831 emitRX(Mips::BGEZ, 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::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002837 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2838 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002839 return false;
2840 }
2841 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002842 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2843 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002844 return false;
2845 }
2846 if (AcceptsEquality) {
2847 // If both registers are $0 and the pseudo-branch accepts equality, it
2848 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002849 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2850 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002851 Warning(IDLoc, "branch is always taken");
2852 return false;
2853 }
2854 // If both registers are $0 and the pseudo-branch does not accept
2855 // equality, it will never be taken, so we don't have to emit anything.
2856 return false;
2857 }
2858 if (IsSrcRegZero || IsTrgRegZero) {
2859 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2860 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2861 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2862 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2863 // the pseudo-branch will never be taken, so we don't emit anything.
2864 // This only applies to unsigned pseudo-branches.
2865 return false;
2866 }
2867 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2868 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2869 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2870 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2871 // the pseudo-branch will always be taken, so we emit an unconditional
2872 // branch.
2873 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002874 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2875 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002876 Warning(IDLoc, "branch is always taken");
2877 return false;
2878 }
2879 if (IsUnsigned) {
2880 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2881 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2882 // the pseudo-branch will be taken only when the non-zero register is
2883 // different from 0, so we emit a BNEZ.
2884 //
2885 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2886 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2887 // the pseudo-branch will be taken only when the non-zero register is
2888 // equal to 0, so we emit a BEQZ.
2889 //
2890 // Because only BLEU and BGEU branch on equality, we can use the
2891 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002892 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2893 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2894 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002895 return false;
2896 }
2897 // If we have a signed pseudo-branch and one of the registers is $0,
2898 // we can use an appropriate compare-to-zero branch. We select which one
2899 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002900 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2901 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2902 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002903 return false;
2904 }
2905
2906 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2907 // expansions. If it is not available, we return.
2908 unsigned ATRegNum = getATReg(IDLoc);
2909 if (!ATRegNum)
2910 return true;
2911
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002912 if (!EmittedNoMacroWarning)
2913 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002914
2915 // SLT fits well with 2 of our 4 pseudo-branches:
2916 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2917 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2918 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2919 // This is accomplished by using a BNEZ with the result of the SLT.
2920 //
2921 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2922 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2923 // Because only BGE and BLE branch on equality, we can use the
2924 // AcceptsEquality variable to decide when to emit the BEQZ.
2925 // Note that the order of the SLT arguments doesn't change between
2926 // opposites.
2927 //
2928 // The same applies to the unsigned variants, except that SLTu is used
2929 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002930 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2931 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2932 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002933
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002934 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2935 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2936 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2937 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002938 return false;
2939}
2940
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002941bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2942 SmallVectorImpl<MCInst> &Instructions,
2943 const bool IsMips64, const bool Signed) {
2944 if (hasMips32r6()) {
2945 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2946 return false;
2947 }
2948
2949 warnIfNoMacro(IDLoc);
2950
2951 const MCOperand &RsRegOp = Inst.getOperand(0);
2952 assert(RsRegOp.isReg() && "expected register operand kind");
2953 unsigned RsReg = RsRegOp.getReg();
2954
2955 const MCOperand &RtRegOp = Inst.getOperand(1);
2956 assert(RtRegOp.isReg() && "expected register operand kind");
2957 unsigned RtReg = RtRegOp.getReg();
2958 unsigned DivOp;
2959 unsigned ZeroReg;
2960
2961 if (IsMips64) {
2962 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2963 ZeroReg = Mips::ZERO_64;
2964 } else {
2965 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2966 ZeroReg = Mips::ZERO;
2967 }
2968
2969 bool UseTraps = useTraps();
2970
2971 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2972 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2973 Warning(IDLoc, "dividing zero by zero");
2974 if (IsMips64) {
2975 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2976 if (UseTraps) {
2977 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2978 return false;
2979 }
2980
2981 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2982 return false;
2983 }
2984 } else {
2985 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2986 return false;
2987 }
2988 }
2989
2990 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2991 Warning(IDLoc, "division by zero");
2992 if (Signed) {
2993 if (UseTraps) {
2994 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2995 return false;
2996 }
2997
2998 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2999 return false;
3000 }
3001 }
3002
3003 // FIXME: The values for these two BranchTarget variables may be different in
3004 // micromips. These magic numbers need to be removed.
3005 unsigned BranchTargetNoTraps;
3006 unsigned BranchTarget;
3007
3008 if (UseTraps) {
3009 BranchTarget = IsMips64 ? 12 : 8;
3010 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3011 } else {
3012 BranchTarget = IsMips64 ? 20 : 16;
3013 BranchTargetNoTraps = 8;
3014 // Branch to the li instruction.
3015 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
3016 Instructions);
3017 }
3018
3019 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3020
3021 if (!UseTraps)
3022 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3023
3024 if (!Signed) {
3025 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3026 return false;
3027 }
3028
3029 unsigned ATReg = getATReg(IDLoc);
3030 if (!ATReg)
3031 return true;
3032
3033 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
3034 if (IsMips64) {
3035 // Branch to the mflo instruction.
3036 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3037 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
3038 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
3039 } else {
3040 // Branch to the mflo instruction.
3041 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3042 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
3043 }
3044
3045 if (UseTraps)
3046 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3047 else {
3048 // Branch to the mflo instruction.
3049 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3050 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3051 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3052 }
3053 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3054 return false;
3055}
3056
Daniel Sanders6394ee52015-10-15 14:52:58 +00003057bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3058 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003059 if (hasMips32r6() || hasMips64r6()) {
3060 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3061 return false;
3062 }
3063
3064 warnIfNoMacro(IDLoc);
3065
3066 const MCOperand &DstRegOp = Inst.getOperand(0);
3067 assert(DstRegOp.isReg() && "expected register operand kind");
3068
3069 const MCOperand &SrcRegOp = Inst.getOperand(1);
3070 assert(SrcRegOp.isReg() && "expected register operand kind");
3071
3072 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3073 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3074
3075 unsigned DstReg = DstRegOp.getReg();
3076 unsigned SrcReg = SrcRegOp.getReg();
3077 int64_t OffsetValue = OffsetImmOp.getImm();
3078
3079 // NOTE: We always need AT for ULHU, as it is always used as the source
3080 // register for one of the LBu's.
3081 unsigned ATReg = getATReg(IDLoc);
3082 if (!ATReg)
3083 return true;
3084
3085 // When the value of offset+1 does not fit in 16 bits, we have to load the
3086 // offset in AT, (D)ADDu the original source register (if there was one), and
3087 // then use AT as the source register for the 2 generated LBu's.
3088 bool LoadedOffsetInAT = false;
3089 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3090 LoadedOffsetInAT = true;
3091
3092 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003093 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003094 return true;
3095
3096 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3097 // because it will make our output more similar to GAS'. For example,
3098 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3099 // instead of just an "ori $1, $9, 32768".
3100 // NOTE: If there is no source register specified in the ULHU, the parser
3101 // will interpret it as $0.
3102 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3103 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3104 }
3105
3106 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3107 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3108 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3109
3110 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3111 if (isLittle()) {
3112 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3113 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3114 } else {
3115 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3116 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3117 }
3118
3119 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3120
Daniel Sanders6394ee52015-10-15 14:52:58 +00003121 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3122 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003123
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003124 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3125 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003126
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003127 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003128
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003129 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003130
3131 return false;
3132}
3133
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003134bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3135 SmallVectorImpl<MCInst> &Instructions) {
3136 if (hasMips32r6() || hasMips64r6()) {
3137 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3138 return false;
3139 }
3140
3141 const MCOperand &DstRegOp = Inst.getOperand(0);
3142 assert(DstRegOp.isReg() && "expected register operand kind");
3143
3144 const MCOperand &SrcRegOp = Inst.getOperand(1);
3145 assert(SrcRegOp.isReg() && "expected register operand kind");
3146
3147 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3148 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3149
3150 unsigned SrcReg = SrcRegOp.getReg();
3151 int64_t OffsetValue = OffsetImmOp.getImm();
3152 unsigned ATReg = 0;
3153
3154 // When the value of offset+3 does not fit in 16 bits, we have to load the
3155 // offset in AT, (D)ADDu the original source register (if there was one), and
3156 // then use AT as the source register for the generated LWL and LWR.
3157 bool LoadedOffsetInAT = false;
3158 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3159 ATReg = getATReg(IDLoc);
3160 if (!ATReg)
3161 return true;
3162 LoadedOffsetInAT = true;
3163
3164 warnIfNoMacro(IDLoc);
3165
3166 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003167 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003168 return true;
3169
3170 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3171 // because it will make our output more similar to GAS'. For example,
3172 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3173 // instead of just an "ori $1, $9, 32768".
3174 // NOTE: If there is no source register specified in the ULW, the parser
3175 // will interpret it as $0.
3176 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3177 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3178 }
3179
3180 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3181 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3182 if (isLittle()) {
3183 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3184 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3185 } else {
3186 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3187 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3188 }
3189
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003190 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3191 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003192
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003193 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3194 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003195
3196 return false;
3197}
3198
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003199bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3200 SmallVectorImpl<MCInst> &Instructions) {
3201
3202 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3203 assert (Inst.getOperand(0).isReg() &&
3204 Inst.getOperand(1).isReg() &&
3205 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3206
3207 unsigned ATReg = Mips::NoRegister;
3208 unsigned FinalDstReg = Mips::NoRegister;
3209 unsigned DstReg = Inst.getOperand(0).getReg();
3210 unsigned SrcReg = Inst.getOperand(1).getReg();
3211 int64_t ImmValue = Inst.getOperand(2).getImm();
3212
3213 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3214
3215 unsigned FinalOpcode = Inst.getOpcode();
3216
3217 if (DstReg == SrcReg) {
3218 ATReg = getATReg(Inst.getLoc());
3219 if (!ATReg)
3220 return true;
3221 FinalDstReg = DstReg;
3222 DstReg = ATReg;
3223 }
3224
3225 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3226 switch (FinalOpcode) {
3227 default:
3228 llvm_unreachable("unimplemented expansion");
3229 case (Mips::ADDi):
3230 FinalOpcode = Mips::ADD;
3231 break;
3232 case (Mips::ADDiu):
3233 FinalOpcode = Mips::ADDu;
3234 break;
3235 case (Mips::ANDi):
3236 FinalOpcode = Mips::AND;
3237 break;
3238 case (Mips::NORImm):
3239 FinalOpcode = Mips::NOR;
3240 break;
3241 case (Mips::ORi):
3242 FinalOpcode = Mips::OR;
3243 break;
3244 case (Mips::SLTi):
3245 FinalOpcode = Mips::SLT;
3246 break;
3247 case (Mips::SLTiu):
3248 FinalOpcode = Mips::SLTu;
3249 break;
3250 case (Mips::XORi):
3251 FinalOpcode = Mips::XOR;
3252 break;
3253 }
3254
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003255 if (FinalDstReg == Mips::NoRegister)
3256 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3257 else
3258 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3259 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003260 return false;
3261 }
3262 return true;
3263}
3264
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003265bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
3266 SmallVectorImpl<MCInst> &Instructions) {
3267 unsigned ATReg = Mips::NoRegister;
3268 unsigned DReg = Inst.getOperand(0).getReg();
3269 unsigned SReg = Inst.getOperand(1).getReg();
3270 unsigned TReg = Inst.getOperand(2).getReg();
3271 unsigned TmpReg = DReg;
3272
3273 unsigned FirstShift = Mips::NOP;
3274 unsigned SecondShift = Mips::NOP;
3275
3276 if (hasMips32r2()) {
3277
3278 if (DReg == SReg) {
3279 TmpReg = getATReg(Inst.getLoc());
3280 if (!TmpReg)
3281 return true;
3282 }
3283
3284 if (Inst.getOpcode() == Mips::ROL) {
3285 emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3286 emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3287 return false;
3288 }
3289
3290 if (Inst.getOpcode() == Mips::ROR) {
3291 emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3292 return false;
3293 }
3294
3295 return true;
3296 }
3297
3298 if (hasMips32()) {
3299
3300 switch (Inst.getOpcode()) {
3301 default:
3302 llvm_unreachable("unexpected instruction opcode");
3303 case Mips::ROL:
3304 FirstShift = Mips::SRLV;
3305 SecondShift = Mips::SLLV;
3306 break;
3307 case Mips::ROR:
3308 FirstShift = Mips::SLLV;
3309 SecondShift = Mips::SRLV;
3310 break;
3311 }
3312
3313 ATReg = getATReg(Inst.getLoc());
3314 if (!ATReg)
3315 return true;
3316
3317 emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3318 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3319 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3320 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3321
3322 return false;
3323 }
3324
3325 return true;
3326}
3327
3328bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
3329 SmallVectorImpl<MCInst> &Instructions) {
3330
3331 unsigned ATReg = Mips::NoRegister;
3332 unsigned DReg = Inst.getOperand(0).getReg();
3333 unsigned SReg = Inst.getOperand(1).getReg();
3334 int64_t ImmValue = Inst.getOperand(2).getImm();
3335
3336 unsigned FirstShift = Mips::NOP;
3337 unsigned SecondShift = Mips::NOP;
3338
3339 if (hasMips32r2()) {
3340
3341 if (Inst.getOpcode() == Mips::ROLImm) {
3342 uint64_t MaxShift = 32;
3343 uint64_t ShiftValue = ImmValue;
3344 if (ImmValue != 0)
3345 ShiftValue = MaxShift - ImmValue;
3346 emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3347 return false;
3348 }
3349
3350 if (Inst.getOpcode() == Mips::RORImm) {
3351 emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3352 return false;
3353 }
3354
3355 return true;
3356 }
3357
3358 if (hasMips32()) {
3359
3360 if (ImmValue == 0) {
3361 emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3362 return false;
3363 }
3364
3365 switch (Inst.getOpcode()) {
3366 default:
3367 llvm_unreachable("unexpected instruction opcode");
3368 case Mips::ROLImm:
3369 FirstShift = Mips::SLL;
3370 SecondShift = Mips::SRL;
3371 break;
3372 case Mips::RORImm:
3373 FirstShift = Mips::SRL;
3374 SecondShift = Mips::SLL;
3375 break;
3376 }
3377
3378 ATReg = getATReg(Inst.getLoc());
3379 if (!ATReg)
3380 return true;
3381
3382 emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3383 emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions);
3384 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3385
3386 return false;
3387 }
3388
3389 return true;
3390}
3391
3392bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
3393 SmallVectorImpl<MCInst> &Instructions) {
3394
3395 unsigned ATReg = Mips::NoRegister;
3396 unsigned DReg = Inst.getOperand(0).getReg();
3397 unsigned SReg = Inst.getOperand(1).getReg();
3398 unsigned TReg = Inst.getOperand(2).getReg();
3399 unsigned TmpReg = DReg;
3400
3401 unsigned FirstShift = Mips::NOP;
3402 unsigned SecondShift = Mips::NOP;
3403
3404 if (hasMips64r2()) {
3405
3406 if (TmpReg == SReg) {
3407 TmpReg = getATReg(Inst.getLoc());
3408 if (!TmpReg)
3409 return true;
3410 }
3411
3412 if (Inst.getOpcode() == Mips::DROL) {
3413 emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3414 emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3415 return false;
3416 }
3417
3418 if (Inst.getOpcode() == Mips::DROR) {
3419 emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3420 return false;
3421 }
3422
3423 return true;
3424 }
3425
3426 if (hasMips64()) {
3427
3428 switch (Inst.getOpcode()) {
3429 default:
3430 llvm_unreachable("unexpected instruction opcode");
3431 case Mips::DROL:
3432 FirstShift = Mips::DSRLV;
3433 SecondShift = Mips::DSLLV;
3434 break;
3435 case Mips::DROR:
3436 FirstShift = Mips::DSLLV;
3437 SecondShift = Mips::DSRLV;
3438 break;
3439 }
3440
3441 ATReg = getATReg(Inst.getLoc());
3442 if (!ATReg)
3443 return true;
3444
3445 emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3446 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3447 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3448 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3449
3450 return false;
3451 }
3452
3453 return true;
3454}
3455
3456bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
3457 SmallVectorImpl<MCInst> &Instructions) {
3458
3459 unsigned ATReg = Mips::NoRegister;
3460 unsigned DReg = Inst.getOperand(0).getReg();
3461 unsigned SReg = Inst.getOperand(1).getReg();
3462 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3463
3464 unsigned FirstShift = Mips::NOP;
3465 unsigned SecondShift = Mips::NOP;
3466
3467 MCInst TmpInst;
3468
3469 if (hasMips64r2()) {
3470
3471 unsigned FinalOpcode = Mips::NOP;
3472 if (ImmValue == 0)
3473 FinalOpcode = Mips::DROTR;
3474 else if (ImmValue % 32 == 0)
3475 FinalOpcode = Mips::DROTR32;
3476 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3477 if (Inst.getOpcode() == Mips::DROLImm)
3478 FinalOpcode = Mips::DROTR32;
3479 else
3480 FinalOpcode = Mips::DROTR;
3481 } else if (ImmValue >= 33) {
3482 if (Inst.getOpcode() == Mips::DROLImm)
3483 FinalOpcode = Mips::DROTR;
3484 else
3485 FinalOpcode = Mips::DROTR32;
3486 }
3487
3488 uint64_t ShiftValue = ImmValue % 32;
3489 if (Inst.getOpcode() == Mips::DROLImm)
3490 ShiftValue = (32 - ImmValue % 32) % 32;
3491
3492 emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3493
3494 return false;
3495 }
3496
3497 if (hasMips64()) {
3498
3499 if (ImmValue == 0) {
3500 emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3501 return false;
3502 }
3503
3504 switch (Inst.getOpcode()) {
3505 default:
3506 llvm_unreachable("unexpected instruction opcode");
3507 case Mips::DROLImm:
3508 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3509 FirstShift = Mips::DSLL;
3510 SecondShift = Mips::DSRL32;
3511 }
3512 if (ImmValue == 32) {
3513 FirstShift = Mips::DSLL32;
3514 SecondShift = Mips::DSRL32;
3515 }
3516 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3517 FirstShift = Mips::DSLL32;
3518 SecondShift = Mips::DSRL;
3519 }
3520 break;
3521 case Mips::DRORImm:
3522 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3523 FirstShift = Mips::DSRL;
3524 SecondShift = Mips::DSLL32;
3525 }
3526 if (ImmValue == 32) {
3527 FirstShift = Mips::DSRL32;
3528 SecondShift = Mips::DSLL32;
3529 }
3530 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3531 FirstShift = Mips::DSRL32;
3532 SecondShift = Mips::DSLL;
3533 }
3534 break;
3535 }
3536
3537 ATReg = getATReg(Inst.getLoc());
3538 if (!ATReg)
3539 return true;
3540
3541 emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions);
3542 emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions);
3543 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3544
3545 return false;
3546 }
3547
3548 return true;
3549}
3550
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003551bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc,
3552 SmallVectorImpl<MCInst> &Instructions) {
3553
3554 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3555 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3556
3557 emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, Instructions);
3558 if (FirstRegOp != SecondRegOp)
3559 emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, Instructions);
3560 else
3561 createNop(false, IDLoc, Instructions);
3562 emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, Instructions);
3563
3564 return false;
3565}
3566
Toma Tabacu234482a2015-03-16 12:03:39 +00003567void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3568 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003569 if (hasShortDelaySlot)
3570 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3571 else
3572 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003573}
3574
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003575void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003576 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003577 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003578 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3579 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003580}
3581
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003582void MipsAsmParser::createCpRestoreMemOp(
3583 bool IsLoad, int StackOffset, SMLoc IDLoc,
3584 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003585 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003586 if (!isInt<16>(StackOffset)) {
3587 MCInst MemInst;
3588 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3589 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3590 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3591 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003592 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003593 return;
3594 }
3595
3596 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3597 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003598}
3599
Matheus Almeida595fcab2014-06-11 15:05:56 +00003600unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3601 // As described by the Mips32r2 spec, the registers Rd and Rs for
3602 // jalr.hb must be different.
3603 unsigned Opcode = Inst.getOpcode();
3604
3605 if (Opcode == Mips::JALR_HB &&
3606 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3607 return Match_RequiresDifferentSrcAndDst;
3608
3609 return Match_Success;
3610}
3611
Daniel Sanders52da7af2015-11-06 12:11:03 +00003612static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3613 uint64_t ErrorInfo) {
3614 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3615 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3616 if (ErrorLoc == SMLoc())
3617 return Loc;
3618 return ErrorLoc;
3619 }
3620 return Loc;
3621}
3622
David Blaikie960ea3f2014-06-08 16:18:35 +00003623bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3624 OperandVector &Operands,
3625 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003626 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003627 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003628
Jack Carterb4dbc172012-09-05 23:34:03 +00003629 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003630 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003631 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003632 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003633
3634 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003635 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003636 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003637 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003638 for (unsigned i = 0; i < Instructions.size(); i++)
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003639 Out.EmitInstruction(Instructions[i], getSTI());
Jack Carterb4dbc172012-09-05 23:34:03 +00003640 return false;
3641 }
3642 case Match_MissingFeature:
3643 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3644 return true;
3645 case Match_InvalidOperand: {
3646 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003647 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003648 if (ErrorInfo >= Operands.size())
3649 return Error(IDLoc, "too few operands for instruction");
3650
Daniel Sanders52da7af2015-11-06 12:11:03 +00003651 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003652 if (ErrorLoc == SMLoc())
3653 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003654 }
3655
3656 return Error(ErrorLoc, "invalid operand for instruction");
3657 }
3658 case Match_MnemonicFail:
3659 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003660 case Match_RequiresDifferentSrcAndDst:
3661 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003662 case Match_Immz:
3663 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003664 case Match_UImm1_0:
3665 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3666 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003667 case Match_UImm2_0:
3668 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3669 "expected 2-bit unsigned immediate");
3670 case Match_UImm2_1:
3671 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3672 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003673 case Match_UImm3_0:
3674 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3675 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003676 case Match_UImm4_0:
3677 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3678 "expected 4-bit unsigned immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003679 case Match_UImm5_0:
3680 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3681 "expected 5-bit unsigned immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003682 case Match_UImm5_1:
3683 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3684 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003685 case Match_UImm5_32:
3686 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3687 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003688 case Match_UImm5_33:
3689 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3690 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003691 case Match_UImm5_0_Report_UImm6:
3692 // This is used on UImm5 operands that have a corresponding UImm5_32
3693 // operand to avoid confusing the user.
3694 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3695 "expected 6-bit unsigned immediate");
3696 case Match_UImm5_Lsl2:
3697 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3698 "expected both 7-bit unsigned immediate and multiple of 4");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003699 case Match_UImm6_0:
3700 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3701 "expected 6-bit unsigned immediate");
Zlatko Buljan252cca52015-12-18 08:59:37 +00003702 case Match_SImm6:
3703 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3704 "expected 6-bit signed immediate");
3705 case Match_UImm7_0:
3706 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3707 "expected 7-bit unsigned immediate");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003708 case Match_UImm8_0:
3709 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3710 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003711 case Match_UImm10_0:
3712 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3713 "expected 10-bit unsigned immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003714 case Match_UImm16:
3715 case Match_UImm16_Relaxed:
3716 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3717 "expected 16-bit unsigned immediate");
Jack Carterb4dbc172012-09-05 23:34:03 +00003718 }
Craig Topper589ceee2015-01-03 08:16:34 +00003719
3720 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003721}
3722
Toma Tabacud9d344b2015-04-27 14:05:04 +00003723void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3724 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3725 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3726 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003727}
3728
Toma Tabacu81496c12015-05-20 08:54:45 +00003729void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3730 if (!AssemblerOptions.back()->isMacro())
3731 Warning(Loc, "macro instruction expanded into multiple instructions");
3732}
3733
Daniel Sandersef638fe2014-10-03 15:37:37 +00003734void
3735MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3736 SMRange Range, bool ShowColors) {
3737 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003738 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003739 ShowColors);
3740}
3741
Jack Carter1ac53222013-02-20 23:11:17 +00003742int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003743 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003744
Vladimir Medic4c299852013-11-06 11:27:05 +00003745 CC = StringSwitch<unsigned>(Name)
3746 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003747 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003748 .Case("a0", 4)
3749 .Case("a1", 5)
3750 .Case("a2", 6)
3751 .Case("a3", 7)
3752 .Case("v0", 2)
3753 .Case("v1", 3)
3754 .Case("s0", 16)
3755 .Case("s1", 17)
3756 .Case("s2", 18)
3757 .Case("s3", 19)
3758 .Case("s4", 20)
3759 .Case("s5", 21)
3760 .Case("s6", 22)
3761 .Case("s7", 23)
3762 .Case("k0", 26)
3763 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003764 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003765 .Case("sp", 29)
3766 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003767 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003768 .Case("ra", 31)
3769 .Case("t0", 8)
3770 .Case("t1", 9)
3771 .Case("t2", 10)
3772 .Case("t3", 11)
3773 .Case("t4", 12)
3774 .Case("t5", 13)
3775 .Case("t6", 14)
3776 .Case("t7", 15)
3777 .Case("t8", 24)
3778 .Case("t9", 25)
3779 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003780
Toma Tabacufda445c2014-09-15 15:33:01 +00003781 if (!(isABI_N32() || isABI_N64()))
3782 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003783
Daniel Sandersef638fe2014-10-03 15:37:37 +00003784 if (12 <= CC && CC <= 15) {
3785 // Name is one of t4-t7
3786 AsmToken RegTok = getLexer().peekTok();
3787 SMRange RegRange = RegTok.getLocRange();
3788
3789 StringRef FixedName = StringSwitch<StringRef>(Name)
3790 .Case("t4", "t0")
3791 .Case("t5", "t1")
3792 .Case("t6", "t2")
3793 .Case("t7", "t3")
3794 .Default("");
3795 assert(FixedName != "" && "Register name is not one of t4-t7.");
3796
3797 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3798 "Did you mean $" + FixedName + "?", RegRange);
3799 }
3800
Toma Tabacufda445c2014-09-15 15:33:01 +00003801 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3802 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3803 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3804 if (8 <= CC && CC <= 11)
3805 CC += 4;
3806
3807 if (CC == -1)
3808 CC = StringSwitch<unsigned>(Name)
3809 .Case("a4", 8)
3810 .Case("a5", 9)
3811 .Case("a6", 10)
3812 .Case("a7", 11)
3813 .Case("kt0", 26)
3814 .Case("kt1", 27)
3815 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003816
3817 return CC;
3818}
Jack Carterd0bd6422013-04-18 00:41:53 +00003819
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003820int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3821 int CC;
3822
3823 CC = StringSwitch<unsigned>(Name)
3824 .Case("hwr_cpunum", 0)
3825 .Case("hwr_synci_step", 1)
3826 .Case("hwr_cc", 2)
3827 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003828 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003829 .Default(-1);
3830
3831 return CC;
3832}
3833
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003834int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003835
Jack Cartera63b16a2012-09-07 00:23:42 +00003836 if (Name[0] == 'f') {
3837 StringRef NumString = Name.substr(1);
3838 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003839 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003840 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003841 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003842 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003843 return IntVal;
3844 }
3845 return -1;
3846}
Jack Cartera63b16a2012-09-07 00:23:42 +00003847
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003848int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3849
3850 if (Name.startswith("fcc")) {
3851 StringRef NumString = Name.substr(3);
3852 unsigned IntVal;
3853 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003854 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003855 if (IntVal > 7) // There are only 8 fcc registers.
3856 return -1;
3857 return IntVal;
3858 }
3859 return -1;
3860}
3861
3862int MipsAsmParser::matchACRegisterName(StringRef Name) {
3863
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003864 if (Name.startswith("ac")) {
3865 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003866 unsigned IntVal;
3867 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003868 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003869 if (IntVal > 3) // There are only 3 acc registers.
3870 return -1;
3871 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003872 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003873 return -1;
3874}
Jack Carterd0bd6422013-04-18 00:41:53 +00003875
Jack Carter5dc8ac92013-09-25 23:50:44 +00003876int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3877 unsigned IntVal;
3878
3879 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3880 return -1;
3881
3882 if (IntVal > 31)
3883 return -1;
3884
3885 return IntVal;
3886}
3887
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003888int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3889 int CC;
3890
3891 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003892 .Case("msair", 0)
3893 .Case("msacsr", 1)
3894 .Case("msaaccess", 2)
3895 .Case("msasave", 3)
3896 .Case("msamodify", 4)
3897 .Case("msarequest", 5)
3898 .Case("msamap", 6)
3899 .Case("msaunmap", 7)
3900 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003901
3902 return CC;
3903}
3904
Toma Tabacu89a712b2015-04-15 10:48:56 +00003905unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003906 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003907 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003908 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003909 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003910 return 0;
3911 }
3912 unsigned AT = getReg(
3913 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003914 return AT;
3915}
Jack Carter0b744b32012-10-04 02:29:46 +00003916
Jack Carterd0bd6422013-04-18 00:41:53 +00003917unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003918 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003919}
3920
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003921unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003922 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003923 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003924}
3925
Jack Carter873c7242013-01-12 01:03:14 +00003926int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003927 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003928 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003929 return -1;
3930
Jack Carter873c7242013-01-12 01:03:14 +00003931 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003932}
3933
Toma Tabacu13964452014-09-04 13:23:44 +00003934bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003935 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003936 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003937
Jack Carter30a59822012-10-04 04:03:53 +00003938 // Check if the current operand has a custom associated parser, if so, try to
3939 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003940 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3941 if (ResTy == MatchOperand_Success)
3942 return false;
3943 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3944 // there was a match, but an error occurred, in which case, just return that
3945 // the operand parsing failed.
3946 if (ResTy == MatchOperand_ParseFail)
3947 return true;
3948
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003949 DEBUG(dbgs() << ".. Generic Parser\n");
3950
Jack Carterb4dbc172012-09-05 23:34:03 +00003951 switch (getLexer().getKind()) {
3952 default:
3953 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3954 return true;
3955 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003956 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003957 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003958
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003959 // Almost all registers have been parsed by custom parsers. There is only
3960 // one exception to this. $zero (and it's alias $0) will reach this point
3961 // for div, divu, and similar instructions because it is not an operand
3962 // to the instruction definition but an explicit register. Special case
3963 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003964 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003965 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003966
Jack Carterd0bd6422013-04-18 00:41:53 +00003967 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003968 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003969 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003970 return true;
3971
Jack Carter873c7242013-01-12 01:03:14 +00003972 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003973 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003974 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003975 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003976 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003977
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003978 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003979 return false;
3980 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003981 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003982 case AsmToken::LParen:
3983 case AsmToken::Minus:
3984 case AsmToken::Plus:
3985 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003986 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003987 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003988 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003989 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003990 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003991 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003992 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003993 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003994 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003995 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003996 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003997 return true;
3998
Jack Carter873c7242013-01-12 01:03:14 +00003999 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4000
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004001 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004002 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004003 } // case AsmToken::Percent
4004 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004005 return true;
4006}
4007
Vladimir Medic4c299852013-11-06 11:27:05 +00004008const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004009 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004010 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00004011 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004012 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00004013 // It's a constant, evaluate reloc value.
4014 int16_t Val;
4015 switch (getVariantKind(RelocStr)) {
4016 case MCSymbolRefExpr::VK_Mips_ABS_LO:
4017 // Get the 1st 16-bits.
4018 Val = MCE->getValue() & 0xffff;
4019 break;
4020 case MCSymbolRefExpr::VK_Mips_ABS_HI:
4021 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
4022 // 16 bits being negative.
4023 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
4024 break;
4025 case MCSymbolRefExpr::VK_Mips_HIGHER:
4026 // Get the 3rd 16-bits.
4027 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
4028 break;
4029 case MCSymbolRefExpr::VK_Mips_HIGHEST:
4030 // Get the 4th 16-bits.
4031 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
4032 break;
4033 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00004034 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00004035 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004036 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004037 }
4038
Jack Carterb5cf5902013-04-17 00:18:04 +00004039 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004040 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00004041 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00004042 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004043 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004044 return Res;
4045 }
4046
4047 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00004048 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
4049
Sasa Stankovic06c47802014-04-03 10:37:45 +00004050 // Try to create target expression.
4051 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00004052 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004053
Jack Carterd0bd6422013-04-18 00:41:53 +00004054 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
4055 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004056 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004057 return Res;
4058 }
4059
4060 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004061 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004062 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00004063 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00004064 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004065 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004066 return Expr;
4067}
4068
4069bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4070
4071 switch (Expr->getKind()) {
4072 case MCExpr::Constant:
4073 return true;
4074 case MCExpr::SymbolRef:
4075 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4076 case MCExpr::Binary:
4077 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4078 if (!isEvaluated(BE->getLHS()))
4079 return false;
4080 return isEvaluated(BE->getRHS());
4081 }
4082 case MCExpr::Unary:
4083 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004084 case MCExpr::Target:
4085 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004086 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004087 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004088}
Jack Carterd0bd6422013-04-18 00:41:53 +00004089
Jack Carterb5cf5902013-04-17 00:18:04 +00004090bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004091 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004092 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004093 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004094 if (Tok.isNot(AsmToken::Identifier))
4095 return true;
4096
Yaron Keren075759a2015-03-30 15:42:36 +00004097 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004098
Jack Carterd0bd6422013-04-18 00:41:53 +00004099 Parser.Lex(); // Eat the identifier.
4100 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004101 const MCExpr *IdVal;
4102 SMLoc EndLoc;
4103
4104 if (getLexer().getKind() == AsmToken::LParen) {
4105 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004106 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004107 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004108 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004109 const AsmToken &nextTok = Parser.getTok();
4110 if (nextTok.isNot(AsmToken::Identifier))
4111 return true;
4112 Str += "(%";
4113 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004114 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004115 if (getLexer().getKind() != AsmToken::LParen)
4116 return true;
4117 } else
4118 break;
4119 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004120 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004121 return true;
4122
4123 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004124 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004125
4126 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004127 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004128
Jack Carterd0bd6422013-04-18 00:41:53 +00004129 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004130 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004131}
4132
Jack Carterb4dbc172012-09-05 23:34:03 +00004133bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4134 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004135 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004136 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004137 if (ResTy == MatchOperand_Success) {
4138 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004139 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004140 StartLoc = Operand.getStartLoc();
4141 EndLoc = Operand.getEndLoc();
4142
4143 // AFAIK, we only support numeric registers and named GPR's in CFI
4144 // directives.
4145 // Don't worry about eating tokens before failing. Using an unrecognised
4146 // register is a parse error.
4147 if (Operand.isGPRAsmReg()) {
4148 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004149 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004150 }
4151
4152 return (RegNo == (unsigned)-1);
4153 }
4154
4155 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004156 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004157}
4158
Jack Carterb5cf5902013-04-17 00:18:04 +00004159bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004160 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004161 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004162 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004163 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004164
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004165 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004166 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004167 ++NumOfLParen;
4168 }
Jack Carter873c7242013-01-12 01:03:14 +00004169
Jack Carterd0bd6422013-04-18 00:41:53 +00004170 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004171 default:
4172 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004173 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004174 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004175 case AsmToken::Integer:
4176 case AsmToken::Minus:
4177 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004178 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004179 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004180 else
4181 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004182 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004183 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004184 break;
Jack Carter873c7242013-01-12 01:03:14 +00004185 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004186 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004187 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004188 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004189}
4190
David Blaikie960ea3f2014-06-08 16:18:35 +00004191MipsAsmParser::OperandMatchResultTy
4192MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004193 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004194 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004195 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004196 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004197 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004198 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004199 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004200 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004201
Jack Carterb5cf5902013-04-17 00:18:04 +00004202 if (getLexer().getKind() == AsmToken::LParen) {
4203 Parser.Lex();
4204 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004205 }
4206
Jack Carterb5cf5902013-04-17 00:18:04 +00004207 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004208 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004209 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004210
Jack Carterd0bd6422013-04-18 00:41:53 +00004211 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004212 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004213 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004214 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004215 SMLoc E =
4216 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004217 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004218 return MatchOperand_Success;
4219 }
4220 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004221 SMLoc E =
4222 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004223
Jack Carterd0bd6422013-04-18 00:41:53 +00004224 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004225 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004226 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004227 S, E, *this);
4228 Operands.push_back(
4229 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004230 return MatchOperand_Success;
4231 }
4232 Error(Parser.getTok().getLoc(), "'(' expected");
4233 return MatchOperand_ParseFail;
4234 }
4235
Jack Carterd0bd6422013-04-18 00:41:53 +00004236 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004237 }
4238
Toma Tabacu13964452014-09-04 13:23:44 +00004239 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004240 if (Res != MatchOperand_Success)
4241 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004242
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004243 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004244 Error(Parser.getTok().getLoc(), "')' expected");
4245 return MatchOperand_ParseFail;
4246 }
4247
Jack Carter873c7242013-01-12 01:03:14 +00004248 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4249
Jack Carterd0bd6422013-04-18 00:41:53 +00004250 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004251
Craig Topper062a2ba2014-04-25 05:30:21 +00004252 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004253 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004254
Jack Carterd0bd6422013-04-18 00:41:53 +00004255 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004256 std::unique_ptr<MipsOperand> op(
4257 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004258 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004259 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004260 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004261 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004262 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4263 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004264 if (IdVal->evaluateAsAbsolute(Imm))
4265 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004266 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004267 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004268 getContext());
4269 }
4270
David Blaikie960ea3f2014-06-08 16:18:35 +00004271 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004272 return MatchOperand_Success;
4273}
4274
David Blaikie960ea3f2014-06-08 16:18:35 +00004275bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004276 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004277 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004278 if (Sym) {
4279 SMLoc S = Parser.getTok().getLoc();
4280 const MCExpr *Expr;
4281 if (Sym->isVariable())
4282 Expr = Sym->getVariableValue();
4283 else
4284 return false;
4285 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004286 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004287 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004288 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004289 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004290 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004291 if (ResTy == MatchOperand_Success) {
4292 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004293 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004294 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004295 llvm_unreachable("Should never ParseFail");
4296 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004297 }
4298 } else if (Expr->getKind() == MCExpr::Constant) {
4299 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004300 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004301 Operands.push_back(
4302 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004303 return true;
4304 }
4305 }
4306 return false;
4307}
Jack Carterd0bd6422013-04-18 00:41:53 +00004308
Jack Carter873c7242013-01-12 01:03:14 +00004309MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004310MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004311 StringRef Identifier,
4312 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004313 int Index = matchCPURegisterName(Identifier);
4314 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004315 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004316 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4317 return MatchOperand_Success;
4318 }
4319
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004320 Index = matchHWRegsRegisterName(Identifier);
4321 if (Index != -1) {
4322 Operands.push_back(MipsOperand::createHWRegsReg(
4323 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4324 return MatchOperand_Success;
4325 }
4326
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004327 Index = matchFPURegisterName(Identifier);
4328 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004329 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004330 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4331 return MatchOperand_Success;
4332 }
4333
4334 Index = matchFCCRegisterName(Identifier);
4335 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004336 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004337 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4338 return MatchOperand_Success;
4339 }
4340
4341 Index = matchACRegisterName(Identifier);
4342 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004343 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004344 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4345 return MatchOperand_Success;
4346 }
4347
4348 Index = matchMSA128RegisterName(Identifier);
4349 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004350 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004351 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4352 return MatchOperand_Success;
4353 }
4354
4355 Index = matchMSA128CtrlRegisterName(Identifier);
4356 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004357 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004358 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4359 return MatchOperand_Success;
4360 }
4361
4362 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004363}
4364
4365MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004366MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004367 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004368 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004369
4370 if (Token.is(AsmToken::Identifier)) {
4371 DEBUG(dbgs() << ".. identifier\n");
4372 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004373 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004374 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004375 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004376 } else if (Token.is(AsmToken::Integer)) {
4377 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004378 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004379 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4380 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004381 return MatchOperand_Success;
4382 }
4383
4384 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4385
4386 return MatchOperand_NoMatch;
4387}
4388
David Blaikie960ea3f2014-06-08 16:18:35 +00004389MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004390MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004391 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004392 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004393
4394 auto Token = Parser.getTok();
4395
4396 SMLoc S = Token.getLoc();
4397
4398 if (Token.isNot(AsmToken::Dollar)) {
4399 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4400 if (Token.is(AsmToken::Identifier)) {
4401 if (searchSymbolAlias(Operands))
4402 return MatchOperand_Success;
4403 }
4404 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4405 return MatchOperand_NoMatch;
4406 }
4407 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004408
Toma Tabacu13964452014-09-04 13:23:44 +00004409 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004410 if (ResTy == MatchOperand_Success) {
4411 Parser.Lex(); // $
4412 Parser.Lex(); // identifier
4413 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004414 return ResTy;
4415}
4416
4417MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004418MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004419 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004420 switch (getLexer().getKind()) {
4421 default:
4422 return MatchOperand_NoMatch;
4423 case AsmToken::LParen:
4424 case AsmToken::Minus:
4425 case AsmToken::Plus:
4426 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004427 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004428 case AsmToken::String:
4429 break;
4430 }
4431
4432 const MCExpr *IdVal;
4433 SMLoc S = Parser.getTok().getLoc();
4434 if (getParser().parseExpression(IdVal))
4435 return MatchOperand_ParseFail;
4436
4437 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4438 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4439 return MatchOperand_Success;
4440}
4441
David Blaikie960ea3f2014-06-08 16:18:35 +00004442MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004443MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004444 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004445 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004446
4447 SMLoc S = getLexer().getLoc();
4448
4449 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004450 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004451 if (ResTy != MatchOperand_NoMatch)
4452 return ResTy;
4453
Daniel Sanders315386c2014-04-01 10:40:14 +00004454 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004455 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004456 if (ResTy != MatchOperand_NoMatch)
4457 return ResTy;
4458
Daniel Sandersffd84362014-04-01 10:41:48 +00004459 const MCExpr *Expr = nullptr;
4460 if (Parser.parseExpression(Expr)) {
4461 // We have no way of knowing if a symbol was consumed so we must ParseFail
4462 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004463 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004464 Operands.push_back(
4465 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004466 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004467}
4468
Vladimir Medic2b953d02013-10-01 09:48:56 +00004469MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004470MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004471 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004472 const MCExpr *IdVal;
4473 // If the first token is '$' we may have register operand.
4474 if (Parser.getTok().is(AsmToken::Dollar))
4475 return MatchOperand_NoMatch;
4476 SMLoc S = Parser.getTok().getLoc();
4477 if (getParser().parseExpression(IdVal))
4478 return MatchOperand_ParseFail;
4479 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004480 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004481 int64_t Val = MCE->getValue();
4482 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4483 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004484 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004485 return MatchOperand_Success;
4486}
4487
Matheus Almeida779c5932013-11-18 12:32:49 +00004488MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004489MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004490 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004491 switch (getLexer().getKind()) {
4492 default:
4493 return MatchOperand_NoMatch;
4494 case AsmToken::LParen:
4495 case AsmToken::Plus:
4496 case AsmToken::Minus:
4497 case AsmToken::Integer:
4498 break;
4499 }
4500
4501 const MCExpr *Expr;
4502 SMLoc S = Parser.getTok().getLoc();
4503
4504 if (getParser().parseExpression(Expr))
4505 return MatchOperand_ParseFail;
4506
4507 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004508 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004509 Error(S, "expected immediate value");
4510 return MatchOperand_ParseFail;
4511 }
4512
4513 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4514 // and because the CPU always adds one to the immediate field, the allowed
4515 // range becomes 1..4. We'll only check the range here and will deal
4516 // with the addition/subtraction when actually decoding/encoding
4517 // the instruction.
4518 if (Val < 1 || Val > 4) {
4519 Error(S, "immediate not in range (1..4)");
4520 return MatchOperand_ParseFail;
4521 }
4522
Jack Carter3b2c96e2014-01-22 23:31:38 +00004523 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004524 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004525 return MatchOperand_Success;
4526}
4527
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004528MipsAsmParser::OperandMatchResultTy
4529MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4530 MCAsmParser &Parser = getParser();
4531 SmallVector<unsigned, 10> Regs;
4532 unsigned RegNo;
4533 unsigned PrevReg = Mips::NoRegister;
4534 bool RegRange = false;
4535 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4536
4537 if (Parser.getTok().isNot(AsmToken::Dollar))
4538 return MatchOperand_ParseFail;
4539
4540 SMLoc S = Parser.getTok().getLoc();
4541 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4542 SMLoc E = getLexer().getLoc();
4543 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4544 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4545 if (RegRange) {
4546 // Remove last register operand because registers from register range
4547 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004548 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4549 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004550 Regs.push_back(RegNo);
4551 } else {
4552 unsigned TmpReg = PrevReg + 1;
4553 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004554 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4555 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4556 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004557 Error(E, "invalid register operand");
4558 return MatchOperand_ParseFail;
4559 }
4560
4561 PrevReg = TmpReg;
4562 Regs.push_back(TmpReg++);
4563 }
4564 }
4565
4566 RegRange = false;
4567 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004568 if ((PrevReg == Mips::NoRegister) &&
4569 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4570 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004571 Error(E, "$16 or $31 expected");
4572 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004573 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4574 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4575 !isGP64bit()) ||
4576 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4577 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4578 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004579 Error(E, "invalid register operand");
4580 return MatchOperand_ParseFail;
4581 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004582 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4583 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4584 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004585 Error(E, "consecutive register numbers expected");
4586 return MatchOperand_ParseFail;
4587 }
4588
4589 Regs.push_back(RegNo);
4590 }
4591
4592 if (Parser.getTok().is(AsmToken::Minus))
4593 RegRange = true;
4594
4595 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4596 !Parser.getTok().isNot(AsmToken::Comma)) {
4597 Error(E, "',' or '-' expected");
4598 return MatchOperand_ParseFail;
4599 }
4600
4601 Lex(); // Consume comma or minus
4602 if (Parser.getTok().isNot(AsmToken::Dollar))
4603 break;
4604
4605 PrevReg = RegNo;
4606 }
4607
4608 SMLoc E = Parser.getTok().getLoc();
4609 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4610 parseMemOperand(Operands);
4611 return MatchOperand_Success;
4612}
4613
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004614MipsAsmParser::OperandMatchResultTy
4615MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4616 MCAsmParser &Parser = getParser();
4617
4618 SMLoc S = Parser.getTok().getLoc();
4619 if (parseAnyRegister(Operands) != MatchOperand_Success)
4620 return MatchOperand_ParseFail;
4621
4622 SMLoc E = Parser.getTok().getLoc();
4623 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4624 unsigned Reg = Op.getGPR32Reg();
4625 Operands.pop_back();
4626 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4627 return MatchOperand_Success;
4628}
4629
Zoran Jovanovic41688672015-02-10 16:36:20 +00004630MipsAsmParser::OperandMatchResultTy
4631MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4632 MCAsmParser &Parser = getParser();
4633 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4634 SmallVector<unsigned, 10> Regs;
4635
4636 if (Parser.getTok().isNot(AsmToken::Dollar))
4637 return MatchOperand_ParseFail;
4638
4639 SMLoc S = Parser.getTok().getLoc();
4640
4641 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4642 return MatchOperand_ParseFail;
4643
4644 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4645 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4646 Regs.push_back(RegNo);
4647
4648 SMLoc E = Parser.getTok().getLoc();
4649 if (Parser.getTok().isNot(AsmToken::Comma)) {
4650 Error(E, "',' expected");
4651 return MatchOperand_ParseFail;
4652 }
4653
4654 // Remove comma.
4655 Parser.Lex();
4656
4657 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4658 return MatchOperand_ParseFail;
4659
4660 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4661 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4662 Regs.push_back(RegNo);
4663
4664 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4665
4666 return MatchOperand_Success;
4667}
4668
Jack Carterdc1e35d2012-09-06 20:00:02 +00004669MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4670
Vladimir Medic4c299852013-11-06 11:27:05 +00004671 MCSymbolRefExpr::VariantKind VK =
4672 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4673 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4674 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4675 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4676 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4677 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4678 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4679 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4680 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4681 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4682 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4683 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4684 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4685 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4686 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4687 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4688 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4689 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004690 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4691 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4692 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4693 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4694 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4695 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004696 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4697 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004698 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004699
Matheus Almeida2852af82014-04-22 10:15:54 +00004700 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004701
Jack Carterdc1e35d2012-09-06 20:00:02 +00004702 return VK;
4703}
Jack Cartera63b16a2012-09-07 00:23:42 +00004704
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004705/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4706/// either this.
4707/// ::= '(', register, ')'
4708/// handle it before we iterate so we don't get tripped up by the lack of
4709/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004710bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004711 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004712 if (getLexer().is(AsmToken::LParen)) {
4713 Operands.push_back(
4714 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4715 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004716 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004717 SMLoc Loc = getLexer().getLoc();
4718 Parser.eatToEndOfStatement();
4719 return Error(Loc, "unexpected token in argument list");
4720 }
4721 if (Parser.getTok().isNot(AsmToken::RParen)) {
4722 SMLoc Loc = getLexer().getLoc();
4723 Parser.eatToEndOfStatement();
4724 return Error(Loc, "unexpected token, expected ')'");
4725 }
4726 Operands.push_back(
4727 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4728 Parser.Lex();
4729 }
4730 return false;
4731}
4732
4733/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4734/// either one of these.
4735/// ::= '[', register, ']'
4736/// ::= '[', integer, ']'
4737/// handle it before we iterate so we don't get tripped up by the lack of
4738/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004739bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004740 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004741 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004742 if (getLexer().is(AsmToken::LBrac)) {
4743 Operands.push_back(
4744 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4745 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004746 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004747 SMLoc Loc = getLexer().getLoc();
4748 Parser.eatToEndOfStatement();
4749 return Error(Loc, "unexpected token in argument list");
4750 }
4751 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4752 SMLoc Loc = getLexer().getLoc();
4753 Parser.eatToEndOfStatement();
4754 return Error(Loc, "unexpected token, expected ']'");
4755 }
4756 Operands.push_back(
4757 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4758 Parser.Lex();
4759 }
4760 return false;
4761}
4762
David Blaikie960ea3f2014-06-08 16:18:35 +00004763bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4764 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004765 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004766 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004767
4768 // We have reached first instruction, module directive are now forbidden.
4769 getTargetStreamer().forbidModuleDirective();
4770
Vladimir Medic74593e62013-07-17 15:00:42 +00004771 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004772 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004773 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004774 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004775 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004776 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004777 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004778
4779 // Read the remaining operands.
4780 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4781 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004782 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004783 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004784 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004785 return Error(Loc, "unexpected token in argument list");
4786 }
Toma Tabacu13964452014-09-04 13:23:44 +00004787 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004788 return true;
4789 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004790
Jack Carterd0bd6422013-04-18 00:41:53 +00004791 while (getLexer().is(AsmToken::Comma)) {
4792 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004793 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004794 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004795 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004796 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004797 return Error(Loc, "unexpected token in argument list");
4798 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004799 // Parse bracket and parenthesis suffixes before we iterate
4800 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004801 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004802 return true;
4803 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004804 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004805 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004806 }
4807 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004808 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4809 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004810 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004811 return Error(Loc, "unexpected token in argument list");
4812 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004813 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004814 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004815}
4816
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004817bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004818 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004819 SMLoc Loc = getLexer().getLoc();
4820 Parser.eatToEndOfStatement();
4821 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004822}
4823
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004824bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004825 return Error(Loc, ErrorMsg);
4826}
4827
Jack Carter0b744b32012-10-04 02:29:46 +00004828bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004829 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004830 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004831
4832 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004833 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004834
4835 Parser.Lex(); // Eat "noat".
4836
Jack Carterd0bd6422013-04-18 00:41:53 +00004837 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004838 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004839 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004840 return false;
4841 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004842
4843 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004844 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004845 return false;
4846}
Jack Carterd0bd6422013-04-18 00:41:53 +00004847
Jack Carter0b744b32012-10-04 02:29:46 +00004848bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004849 // Line can be: ".set at", which sets $at to $1
4850 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004851 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004852 Parser.Lex(); // Eat "at".
4853
Jack Carter0b744b32012-10-04 02:29:46 +00004854 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004855 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004856 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004857
4858 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004859 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004860 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004861 }
4862
4863 if (getLexer().isNot(AsmToken::Equal)) {
4864 reportParseError("unexpected token, expected equals sign");
4865 return false;
4866 }
4867 Parser.Lex(); // Eat "=".
4868
4869 if (getLexer().isNot(AsmToken::Dollar)) {
4870 if (getLexer().is(AsmToken::EndOfStatement)) {
4871 reportParseError("no register specified");
4872 return false;
4873 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004874 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004875 return false;
4876 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004877 }
4878 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004879
Toma Tabacu16a74492015-02-13 10:30:57 +00004880 // Find out what "reg" is.
4881 unsigned AtRegNo;
4882 const AsmToken &Reg = Parser.getTok();
4883 if (Reg.is(AsmToken::Identifier)) {
4884 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4885 } else if (Reg.is(AsmToken::Integer)) {
4886 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004887 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004888 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004889 return false;
4890 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004891
4892 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004893 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004894 reportParseError("invalid register");
4895 return false;
4896 }
4897 Parser.Lex(); // Eat "reg".
4898
4899 // If this is not the end of the statement, report an error.
4900 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4901 reportParseError("unexpected token, expected end of statement");
4902 return false;
4903 }
4904
4905 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4906
4907 Parser.Lex(); // Consume the EndOfStatement.
4908 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004909}
4910
4911bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004912 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004913 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004914 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004915 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004916 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004917 return false;
4918 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004919 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004920 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004921 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004922 return false;
4923}
4924
4925bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004926 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004927 Parser.Lex();
4928 // If this is not the end of the statement, report an error.
4929 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004930 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004931 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004932 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004933 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004934 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004935 Parser.Lex(); // Consume the EndOfStatement.
4936 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004937}
4938
4939bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004940 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004941 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004942 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004943 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004944 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004945 return false;
4946 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004947 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004948 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004949 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004950 return false;
4951}
4952
4953bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004954 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004955 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004956 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004957 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004958 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004959 return false;
4960 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004961 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004962 reportParseError("`noreorder' must be set before `nomacro'");
4963 return false;
4964 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004965 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004966 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004967 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004968 return false;
4969}
Jack Carterd76b2372013-03-21 21:44:16 +00004970
Daniel Sanders44934432014-08-07 12:03:36 +00004971bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004972 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004973 Parser.Lex();
4974
4975 // If this is not the end of the statement, report an error.
4976 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004977 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004978
4979 setFeatureBits(Mips::FeatureMSA, "msa");
4980 getTargetStreamer().emitDirectiveSetMsa();
4981 return false;
4982}
4983
4984bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004985 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004986 Parser.Lex();
4987
4988 // If this is not the end of the statement, report an error.
4989 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004990 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004991
4992 clearFeatureBits(Mips::FeatureMSA, "msa");
4993 getTargetStreamer().emitDirectiveSetNoMsa();
4994 return false;
4995}
4996
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004997bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004998 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004999 Parser.Lex(); // Eat "nodsp".
5000
5001 // If this is not the end of the statement, report an error.
5002 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5003 reportParseError("unexpected token, expected end of statement");
5004 return false;
5005 }
5006
5007 clearFeatureBits(Mips::FeatureDSP, "dsp");
5008 getTargetStreamer().emitDirectiveSetNoDsp();
5009 return false;
5010}
5011
Toma Tabacucc2502d2014-11-04 17:18:07 +00005012bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005013 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005014 Parser.Lex(); // Eat "mips16".
5015
Jack Carter39536722014-01-22 23:08:42 +00005016 // If this is not the end of the statement, report an error.
5017 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005018 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005019 return false;
5020 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005021
5022 setFeatureBits(Mips::FeatureMips16, "mips16");
5023 getTargetStreamer().emitDirectiveSetMips16();
5024 Parser.Lex(); // Consume the EndOfStatement.
5025 return false;
5026}
5027
5028bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005029 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005030 Parser.Lex(); // Eat "nomips16".
5031
5032 // If this is not the end of the statement, report an error.
5033 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5034 reportParseError("unexpected token, expected end of statement");
5035 return false;
5036 }
5037
5038 clearFeatureBits(Mips::FeatureMips16, "mips16");
5039 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005040 Parser.Lex(); // Consume the EndOfStatement.
5041 return false;
5042}
5043
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005044bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005045 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005046 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005047 // Line can be: .set fp=32
5048 // .set fp=xx
5049 // .set fp=64
5050 Parser.Lex(); // Eat fp token
5051 AsmToken Tok = Parser.getTok();
5052 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005053 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005054 return false;
5055 }
5056 Parser.Lex(); // Eat '=' token.
5057 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005058
5059 if (!parseFpABIValue(FpAbiVal, ".set"))
5060 return false;
5061
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005062 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005063 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005064 return false;
5065 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005066 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005067 Parser.Lex(); // Consume the EndOfStatement.
5068 return false;
5069}
5070
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005071bool MipsAsmParser::parseSetOddSPRegDirective() {
5072 MCAsmParser &Parser = getParser();
5073
5074 Parser.Lex(); // Eat "oddspreg".
5075 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5076 reportParseError("unexpected token, expected end of statement");
5077 return false;
5078 }
5079
5080 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5081 getTargetStreamer().emitDirectiveSetOddSPReg();
5082 return false;
5083}
5084
5085bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5086 MCAsmParser &Parser = getParser();
5087
5088 Parser.Lex(); // Eat "nooddspreg".
5089 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5090 reportParseError("unexpected token, expected end of statement");
5091 return false;
5092 }
5093
5094 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5095 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5096 return false;
5097}
5098
Toma Tabacu9db22db2014-09-09 10:15:38 +00005099bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005100 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005101 SMLoc Loc = getLexer().getLoc();
5102
5103 Parser.Lex();
5104 if (getLexer().isNot(AsmToken::EndOfStatement))
5105 return reportParseError("unexpected token, expected end of statement");
5106
5107 // Always keep an element on the options "stack" to prevent the user
5108 // from changing the initial options. This is how we remember them.
5109 if (AssemblerOptions.size() == 2)
5110 return reportParseError(Loc, ".set pop with no .set push");
5111
Akira Hatanakab11ef082015-11-14 06:35:56 +00005112 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005113 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005114 setAvailableFeatures(
5115 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5116 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005117
5118 getTargetStreamer().emitDirectiveSetPop();
5119 return false;
5120}
5121
5122bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005123 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005124 Parser.Lex();
5125 if (getLexer().isNot(AsmToken::EndOfStatement))
5126 return reportParseError("unexpected token, expected end of statement");
5127
5128 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005129 AssemblerOptions.push_back(
5130 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005131
5132 getTargetStreamer().emitDirectiveSetPush();
5133 return false;
5134}
5135
Toma Tabacu29696502015-06-02 09:48:04 +00005136bool MipsAsmParser::parseSetSoftFloatDirective() {
5137 MCAsmParser &Parser = getParser();
5138 Parser.Lex();
5139 if (getLexer().isNot(AsmToken::EndOfStatement))
5140 return reportParseError("unexpected token, expected end of statement");
5141
5142 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5143 getTargetStreamer().emitDirectiveSetSoftFloat();
5144 return false;
5145}
5146
5147bool MipsAsmParser::parseSetHardFloatDirective() {
5148 MCAsmParser &Parser = getParser();
5149 Parser.Lex();
5150 if (getLexer().isNot(AsmToken::EndOfStatement))
5151 return reportParseError("unexpected token, expected end of statement");
5152
5153 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5154 getTargetStreamer().emitDirectiveSetHardFloat();
5155 return false;
5156}
5157
Jack Carterd76b2372013-03-21 21:44:16 +00005158bool MipsAsmParser::parseSetAssignment() {
5159 StringRef Name;
5160 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005161 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005162
5163 if (Parser.parseIdentifier(Name))
5164 reportParseError("expected identifier after .set");
5165
5166 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005167 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005168 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005169
Jack Carter3b2c96e2014-01-22 23:31:38 +00005170 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005171 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005172
Jim Grosbach6f482002015-05-18 18:43:14 +00005173 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005174 Sym->setVariableValue(Value);
5175
5176 return false;
5177}
Jack Carterd0bd6422013-04-18 00:41:53 +00005178
Toma Tabacu26647792014-09-09 12:52:14 +00005179bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005180 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005181 Parser.Lex();
5182 if (getLexer().isNot(AsmToken::EndOfStatement))
5183 return reportParseError("unexpected token, expected end of statement");
5184
5185 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005186 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005187 setAvailableFeatures(
5188 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5189 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005190 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5191
5192 getTargetStreamer().emitDirectiveSetMips0();
5193 return false;
5194}
5195
Toma Tabacu85618b32014-08-19 14:22:52 +00005196bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005197 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005198 Parser.Lex();
5199 if (getLexer().isNot(AsmToken::Equal))
5200 return reportParseError("unexpected token, expected equals sign");
5201
5202 Parser.Lex();
5203 StringRef Arch;
5204 if (Parser.parseIdentifier(Arch))
5205 return reportParseError("expected arch identifier");
5206
5207 StringRef ArchFeatureName =
5208 StringSwitch<StringRef>(Arch)
5209 .Case("mips1", "mips1")
5210 .Case("mips2", "mips2")
5211 .Case("mips3", "mips3")
5212 .Case("mips4", "mips4")
5213 .Case("mips5", "mips5")
5214 .Case("mips32", "mips32")
5215 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005216 .Case("mips32r3", "mips32r3")
5217 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005218 .Case("mips32r6", "mips32r6")
5219 .Case("mips64", "mips64")
5220 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005221 .Case("mips64r3", "mips64r3")
5222 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005223 .Case("mips64r6", "mips64r6")
5224 .Case("cnmips", "cnmips")
5225 .Case("r4000", "mips3") // This is an implementation of Mips3.
5226 .Default("");
5227
5228 if (ArchFeatureName.empty())
5229 return reportParseError("unsupported architecture");
5230
5231 selectArch(ArchFeatureName);
5232 getTargetStreamer().emitDirectiveSetArch(Arch);
5233 return false;
5234}
5235
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005236bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005237 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005238 Parser.Lex();
5239 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005240 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005241
Matheus Almeida2852af82014-04-22 10:15:54 +00005242 switch (Feature) {
5243 default:
5244 llvm_unreachable("Unimplemented feature");
5245 case Mips::FeatureDSP:
5246 setFeatureBits(Mips::FeatureDSP, "dsp");
5247 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005248 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005249 case Mips::FeatureMicroMips:
5250 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005251 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005252 case Mips::FeatureMips1:
5253 selectArch("mips1");
5254 getTargetStreamer().emitDirectiveSetMips1();
5255 break;
5256 case Mips::FeatureMips2:
5257 selectArch("mips2");
5258 getTargetStreamer().emitDirectiveSetMips2();
5259 break;
5260 case Mips::FeatureMips3:
5261 selectArch("mips3");
5262 getTargetStreamer().emitDirectiveSetMips3();
5263 break;
5264 case Mips::FeatureMips4:
5265 selectArch("mips4");
5266 getTargetStreamer().emitDirectiveSetMips4();
5267 break;
5268 case Mips::FeatureMips5:
5269 selectArch("mips5");
5270 getTargetStreamer().emitDirectiveSetMips5();
5271 break;
5272 case Mips::FeatureMips32:
5273 selectArch("mips32");
5274 getTargetStreamer().emitDirectiveSetMips32();
5275 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005276 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005277 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005278 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005279 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005280 case Mips::FeatureMips32r3:
5281 selectArch("mips32r3");
5282 getTargetStreamer().emitDirectiveSetMips32R3();
5283 break;
5284 case Mips::FeatureMips32r5:
5285 selectArch("mips32r5");
5286 getTargetStreamer().emitDirectiveSetMips32R5();
5287 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005288 case Mips::FeatureMips32r6:
5289 selectArch("mips32r6");
5290 getTargetStreamer().emitDirectiveSetMips32R6();
5291 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005292 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005293 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005294 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005295 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005296 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005297 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005298 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005299 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005300 case Mips::FeatureMips64r3:
5301 selectArch("mips64r3");
5302 getTargetStreamer().emitDirectiveSetMips64R3();
5303 break;
5304 case Mips::FeatureMips64r5:
5305 selectArch("mips64r5");
5306 getTargetStreamer().emitDirectiveSetMips64R5();
5307 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005308 case Mips::FeatureMips64r6:
5309 selectArch("mips64r6");
5310 getTargetStreamer().emitDirectiveSetMips64R6();
5311 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005312 }
5313 return false;
5314}
5315
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005316bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005317 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005318 if (getLexer().isNot(AsmToken::Comma)) {
5319 SMLoc Loc = getLexer().getLoc();
5320 Parser.eatToEndOfStatement();
5321 return Error(Loc, ErrorStr);
5322 }
5323
Matheus Almeida2852af82014-04-22 10:15:54 +00005324 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005325 return true;
5326}
5327
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005328// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5329// In this class, it is only used for .cprestore.
5330// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5331// MipsTargetELFStreamer and MipsAsmParser.
5332bool MipsAsmParser::isPicAndNotNxxAbi() {
5333 return inPicMode() && !(isABI_N32() || isABI_N64());
5334}
5335
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005336bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005337 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005338 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005339
Toma Tabacudde4c462014-11-06 10:02:45 +00005340 if (inMips16Mode()) {
5341 reportParseError(".cpload is not supported in Mips16 mode");
5342 return false;
5343 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005344
David Blaikie960ea3f2014-06-08 16:18:35 +00005345 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005346 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005347 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5348 reportParseError("expected register containing function address");
5349 return false;
5350 }
5351
David Blaikie960ea3f2014-06-08 16:18:35 +00005352 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5353 if (!RegOpnd.isGPRAsmReg()) {
5354 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005355 return false;
5356 }
5357
Toma Tabacudde4c462014-11-06 10:02:45 +00005358 // If this is not the end of the statement, report an error.
5359 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5360 reportParseError("unexpected token, expected end of statement");
5361 return false;
5362 }
5363
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005364 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005365 return false;
5366}
5367
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005368bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5369 MCAsmParser &Parser = getParser();
5370
5371 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5372 // is used in non-PIC mode.
5373
5374 if (inMips16Mode()) {
5375 reportParseError(".cprestore is not supported in Mips16 mode");
5376 return false;
5377 }
5378
5379 // Get the stack offset value.
5380 const MCExpr *StackOffset;
5381 int64_t StackOffsetVal;
5382 if (Parser.parseExpression(StackOffset)) {
5383 reportParseError("expected stack offset value");
5384 return false;
5385 }
5386
5387 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5388 reportParseError("stack offset is not an absolute expression");
5389 return false;
5390 }
5391
5392 if (StackOffsetVal < 0) {
5393 Warning(Loc, ".cprestore with negative stack offset has no effect");
5394 IsCpRestoreSet = false;
5395 } else {
5396 IsCpRestoreSet = true;
5397 CpRestoreOffset = StackOffsetVal;
5398 }
5399
5400 // If this is not the end of the statement, report an error.
5401 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5402 reportParseError("unexpected token, expected end of statement");
5403 return false;
5404 }
5405
5406 // Store the $gp on the stack.
5407 SmallVector<MCInst, 3> StoreInsts;
5408 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5409 StoreInsts);
5410
5411 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5412 Parser.Lex(); // Consume the EndOfStatement.
5413 return false;
5414}
5415
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005416bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005417 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005418 unsigned FuncReg;
5419 unsigned Save;
5420 bool SaveIsReg = true;
5421
Matheus Almeida7e815762014-06-18 13:08:59 +00005422 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005423 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005424 if (ResTy == MatchOperand_NoMatch) {
5425 reportParseError("expected register containing function address");
5426 Parser.eatToEndOfStatement();
5427 return false;
5428 }
5429
5430 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5431 if (!FuncRegOpnd.isGPRAsmReg()) {
5432 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5433 Parser.eatToEndOfStatement();
5434 return false;
5435 }
5436
5437 FuncReg = FuncRegOpnd.getGPR32Reg();
5438 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005439
Toma Tabacu65f10572014-09-16 15:00:52 +00005440 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005441 return true;
5442
Toma Tabacu13964452014-09-04 13:23:44 +00005443 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005444 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005445 const MCExpr *OffsetExpr;
5446 int64_t OffsetVal;
5447 SMLoc ExprLoc = getLexer().getLoc();
5448
5449 if (Parser.parseExpression(OffsetExpr) ||
5450 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5451 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005452 Parser.eatToEndOfStatement();
5453 return false;
5454 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005455
5456 Save = OffsetVal;
5457 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005458 } else {
5459 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5460 if (!SaveOpnd.isGPRAsmReg()) {
5461 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5462 Parser.eatToEndOfStatement();
5463 return false;
5464 }
5465 Save = SaveOpnd.getGPR32Reg();
5466 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005467
Toma Tabacu65f10572014-09-16 15:00:52 +00005468 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005469 return true;
5470
Toma Tabacu8874eac2015-02-18 13:46:53 +00005471 const MCExpr *Expr;
5472 if (Parser.parseExpression(Expr)) {
5473 reportParseError("expected expression");
5474 return false;
5475 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005476
Toma Tabacu8874eac2015-02-18 13:46:53 +00005477 if (Expr->getKind() != MCExpr::SymbolRef) {
5478 reportParseError("expected symbol");
5479 return false;
5480 }
5481 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5482
Daniel Sandersf173dda2015-09-22 10:50:09 +00005483 CpSaveLocation = Save;
5484 CpSaveLocationIsRegister = SaveIsReg;
5485
Toma Tabacu8874eac2015-02-18 13:46:53 +00005486 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5487 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005488 return false;
5489}
5490
Daniel Sandersf173dda2015-09-22 10:50:09 +00005491bool MipsAsmParser::parseDirectiveCPReturn() {
5492 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5493 CpSaveLocationIsRegister);
5494 return false;
5495}
5496
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005497bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005498 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005499 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5500 const AsmToken &Tok = Parser.getTok();
5501
5502 if (Tok.getString() == "2008") {
5503 Parser.Lex();
5504 getTargetStreamer().emitDirectiveNaN2008();
5505 return false;
5506 } else if (Tok.getString() == "legacy") {
5507 Parser.Lex();
5508 getTargetStreamer().emitDirectiveNaNLegacy();
5509 return false;
5510 }
5511 }
5512 // If we don't recognize the option passed to the .nan
5513 // directive (e.g. no option or unknown option), emit an error.
5514 reportParseError("invalid option in .nan directive");
5515 return false;
5516}
5517
Jack Carter0b744b32012-10-04 02:29:46 +00005518bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005519 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005520 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005521 const AsmToken &Tok = Parser.getTok();
5522
5523 if (Tok.getString() == "noat") {
5524 return parseSetNoAtDirective();
5525 } else if (Tok.getString() == "at") {
5526 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005527 } else if (Tok.getString() == "arch") {
5528 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005529 } else if (Tok.getString() == "fp") {
5530 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005531 } else if (Tok.getString() == "oddspreg") {
5532 return parseSetOddSPRegDirective();
5533 } else if (Tok.getString() == "nooddspreg") {
5534 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005535 } else if (Tok.getString() == "pop") {
5536 return parseSetPopDirective();
5537 } else if (Tok.getString() == "push") {
5538 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005539 } else if (Tok.getString() == "reorder") {
5540 return parseSetReorderDirective();
5541 } else if (Tok.getString() == "noreorder") {
5542 return parseSetNoReorderDirective();
5543 } else if (Tok.getString() == "macro") {
5544 return parseSetMacroDirective();
5545 } else if (Tok.getString() == "nomacro") {
5546 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005547 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005548 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005549 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005550 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005551 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005552 getTargetStreamer().emitDirectiveSetNoMicroMips();
5553 Parser.eatToEndOfStatement();
5554 return false;
5555 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005556 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005557 } else if (Tok.getString() == "mips0") {
5558 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005559 } else if (Tok.getString() == "mips1") {
5560 return parseSetFeature(Mips::FeatureMips1);
5561 } else if (Tok.getString() == "mips2") {
5562 return parseSetFeature(Mips::FeatureMips2);
5563 } else if (Tok.getString() == "mips3") {
5564 return parseSetFeature(Mips::FeatureMips3);
5565 } else if (Tok.getString() == "mips4") {
5566 return parseSetFeature(Mips::FeatureMips4);
5567 } else if (Tok.getString() == "mips5") {
5568 return parseSetFeature(Mips::FeatureMips5);
5569 } else if (Tok.getString() == "mips32") {
5570 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005571 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005572 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005573 } else if (Tok.getString() == "mips32r3") {
5574 return parseSetFeature(Mips::FeatureMips32r3);
5575 } else if (Tok.getString() == "mips32r5") {
5576 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005577 } else if (Tok.getString() == "mips32r6") {
5578 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005579 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005580 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005581 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005582 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005583 } else if (Tok.getString() == "mips64r3") {
5584 return parseSetFeature(Mips::FeatureMips64r3);
5585 } else if (Tok.getString() == "mips64r5") {
5586 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005587 } else if (Tok.getString() == "mips64r6") {
5588 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005589 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005590 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005591 } else if (Tok.getString() == "nodsp") {
5592 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005593 } else if (Tok.getString() == "msa") {
5594 return parseSetMsaDirective();
5595 } else if (Tok.getString() == "nomsa") {
5596 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005597 } else if (Tok.getString() == "softfloat") {
5598 return parseSetSoftFloatDirective();
5599 } else if (Tok.getString() == "hardfloat") {
5600 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005601 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005602 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005603 parseSetAssignment();
5604 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005605 }
Jack Carter07c818d2013-01-25 01:31:34 +00005606
Jack Carter0b744b32012-10-04 02:29:46 +00005607 return true;
5608}
5609
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005610/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005611/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005612bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005613 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005614 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5615 for (;;) {
5616 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005617 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005618 return true;
5619
5620 getParser().getStreamer().EmitValue(Value, Size);
5621
5622 if (getLexer().is(AsmToken::EndOfStatement))
5623 break;
5624
Jack Carter07c818d2013-01-25 01:31:34 +00005625 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005626 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005627 Parser.Lex();
5628 }
5629 }
5630
5631 Parser.Lex();
5632 return false;
5633}
5634
Vladimir Medic4c299852013-11-06 11:27:05 +00005635/// parseDirectiveGpWord
5636/// ::= .gpword local_sym
5637bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005638 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005639 const MCExpr *Value;
5640 // EmitGPRel32Value requires an expression, so we are using base class
5641 // method to evaluate the expression.
5642 if (getParser().parseExpression(Value))
5643 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005644 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005645
Vladimir Medice10c1122013-11-13 13:18:04 +00005646 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005647 return Error(getLexer().getLoc(),
5648 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005649 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005650 return false;
5651}
5652
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005653/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005654/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005655bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005656 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005657 const MCExpr *Value;
5658 // EmitGPRel64Value requires an expression, so we are using base class
5659 // method to evaluate the expression.
5660 if (getParser().parseExpression(Value))
5661 return true;
5662 getParser().getStreamer().EmitGPRel64Value(Value);
5663
5664 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005665 return Error(getLexer().getLoc(),
5666 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005667 Parser.Lex(); // Eat EndOfStatement token.
5668 return false;
5669}
5670
Jack Carter0cd3c192014-01-06 23:27:31 +00005671bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005672 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005673 // Get the option token.
5674 AsmToken Tok = Parser.getTok();
5675 // At the moment only identifiers are supported.
5676 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005677 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005678 Parser.eatToEndOfStatement();
5679 return false;
5680 }
5681
5682 StringRef Option = Tok.getIdentifier();
5683
5684 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005685 // MipsAsmParser needs to know if the current PIC mode changes.
5686 IsPicEnabled = false;
5687
Jack Carter0cd3c192014-01-06 23:27:31 +00005688 getTargetStreamer().emitDirectiveOptionPic0();
5689 Parser.Lex();
5690 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5691 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005692 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005693 Parser.eatToEndOfStatement();
5694 }
5695 return false;
5696 }
5697
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005698 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005699 // MipsAsmParser needs to know if the current PIC mode changes.
5700 IsPicEnabled = true;
5701
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005702 getTargetStreamer().emitDirectiveOptionPic2();
5703 Parser.Lex();
5704 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5705 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005706 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005707 Parser.eatToEndOfStatement();
5708 }
5709 return false;
5710 }
5711
Jack Carter0cd3c192014-01-06 23:27:31 +00005712 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005713 Warning(Parser.getTok().getLoc(),
5714 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005715 Parser.eatToEndOfStatement();
5716 return false;
5717}
5718
Toma Tabacu9ca50962015-04-16 09:53:47 +00005719/// parseInsnDirective
5720/// ::= .insn
5721bool MipsAsmParser::parseInsnDirective() {
5722 // 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 // The actual label marking happens in
5729 // MipsELFStreamer::createPendingLabelRelocs().
5730 getTargetStreamer().emitDirectiveInsn();
5731
5732 getParser().Lex(); // Eat EndOfStatement token.
5733 return false;
5734}
5735
Daniel Sanders7e527422014-07-10 13:38:23 +00005736/// parseDirectiveModule
5737/// ::= .module oddspreg
5738/// ::= .module nooddspreg
5739/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005740/// ::= .module softfloat
5741/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005742bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005743 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005744 MCAsmLexer &Lexer = getLexer();
5745 SMLoc L = Lexer.getLoc();
5746
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005747 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005748 // TODO : get a better message.
5749 reportParseError(".module directive must appear before any code");
5750 return false;
5751 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005752
Toma Tabacuc405c822015-01-23 10:40:19 +00005753 StringRef Option;
5754 if (Parser.parseIdentifier(Option)) {
5755 reportParseError("expected .module option identifier");
5756 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005757 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005758
Toma Tabacuc405c822015-01-23 10:40:19 +00005759 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005760 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005761
Toma Tabacu3c499582015-06-25 10:56:57 +00005762 // Synchronize the abiflags information with the FeatureBits information we
5763 // changed above.
5764 getTargetStreamer().updateABIInfo(*this);
5765
5766 // If printing assembly, use the recently updated abiflags information.
5767 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5768 // emitted at the end).
5769 getTargetStreamer().emitDirectiveModuleOddSPReg();
5770
Toma Tabacuc405c822015-01-23 10:40:19 +00005771 // If this is not the end of the statement, report an error.
5772 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5773 reportParseError("unexpected token, expected end of statement");
5774 return false;
5775 }
5776
5777 return false; // parseDirectiveModule has finished successfully.
5778 } else if (Option == "nooddspreg") {
5779 if (!isABI_O32()) {
5780 Error(L, "'.module nooddspreg' requires the O32 ABI");
5781 return false;
5782 }
5783
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005784 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005785
Toma Tabacu3c499582015-06-25 10:56:57 +00005786 // Synchronize the abiflags information with the FeatureBits information we
5787 // changed above.
5788 getTargetStreamer().updateABIInfo(*this);
5789
5790 // If printing assembly, use the recently updated abiflags information.
5791 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5792 // emitted at the end).
5793 getTargetStreamer().emitDirectiveModuleOddSPReg();
5794
Toma Tabacuc405c822015-01-23 10:40:19 +00005795 // If this is not the end of the statement, report an error.
5796 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5797 reportParseError("unexpected token, expected end of statement");
5798 return false;
5799 }
5800
5801 return false; // parseDirectiveModule has finished successfully.
5802 } else if (Option == "fp") {
5803 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005804 } else if (Option == "softfloat") {
5805 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5806
5807 // Synchronize the ABI Flags information with the FeatureBits information we
5808 // updated above.
5809 getTargetStreamer().updateABIInfo(*this);
5810
5811 // If printing assembly, use the recently updated ABI Flags information.
5812 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5813 // emitted later).
5814 getTargetStreamer().emitDirectiveModuleSoftFloat();
5815
5816 // If this is not the end of the statement, report an error.
5817 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5818 reportParseError("unexpected token, expected end of statement");
5819 return false;
5820 }
5821
5822 return false; // parseDirectiveModule has finished successfully.
5823 } else if (Option == "hardfloat") {
5824 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5825
5826 // Synchronize the ABI Flags information with the FeatureBits information we
5827 // updated above.
5828 getTargetStreamer().updateABIInfo(*this);
5829
5830 // If printing assembly, use the recently updated ABI Flags information.
5831 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5832 // emitted later).
5833 getTargetStreamer().emitDirectiveModuleHardFloat();
5834
5835 // If this is not the end of the statement, report an error.
5836 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5837 reportParseError("unexpected token, expected end of statement");
5838 return false;
5839 }
5840
5841 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005842 } else {
5843 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5844 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005845}
5846
5847/// parseDirectiveModuleFP
5848/// ::= =32
5849/// ::= =xx
5850/// ::= =64
5851bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005852 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005853 MCAsmLexer &Lexer = getLexer();
5854
5855 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005856 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005857 return false;
5858 }
5859 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005860
Daniel Sanders7e527422014-07-10 13:38:23 +00005861 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005862 if (!parseFpABIValue(FpABI, ".module"))
5863 return false;
5864
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005865 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005866 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005867 return false;
5868 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005869
Toma Tabacua64e5402015-06-25 12:44:38 +00005870 // Synchronize the abiflags information with the FeatureBits information we
5871 // changed above.
5872 getTargetStreamer().updateABIInfo(*this);
5873
5874 // If printing assembly, use the recently updated abiflags information.
5875 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5876 // emitted at the end).
5877 getTargetStreamer().emitDirectiveModuleFP();
5878
Daniel Sanders7e527422014-07-10 13:38:23 +00005879 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005880 return false;
5881}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005882
Daniel Sanders7e527422014-07-10 13:38:23 +00005883bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005884 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005885 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005886 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005887 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005888
5889 if (Lexer.is(AsmToken::Identifier)) {
5890 StringRef Value = Parser.getTok().getString();
5891 Parser.Lex();
5892
5893 if (Value != "xx") {
5894 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5895 return false;
5896 }
5897
5898 if (!isABI_O32()) {
5899 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5900 return false;
5901 }
5902
Daniel Sanders7e527422014-07-10 13:38:23 +00005903 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005904 if (ModuleLevelOptions) {
5905 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5906 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5907 } else {
5908 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5909 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5910 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005911 return true;
5912 }
5913
5914 if (Lexer.is(AsmToken::Integer)) {
5915 unsigned Value = Parser.getTok().getIntVal();
5916 Parser.Lex();
5917
5918 if (Value != 32 && Value != 64) {
5919 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5920 return false;
5921 }
5922
5923 if (Value == 32) {
5924 if (!isABI_O32()) {
5925 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5926 return false;
5927 }
5928
Daniel Sanders7e527422014-07-10 13:38:23 +00005929 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005930 if (ModuleLevelOptions) {
5931 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5932 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5933 } else {
5934 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5935 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5936 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005937 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005938 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005939 if (ModuleLevelOptions) {
5940 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5941 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5942 } else {
5943 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5944 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5945 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005946 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005947
Daniel Sanders7e527422014-07-10 13:38:23 +00005948 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005949 }
5950
5951 return false;
5952}
5953
Jack Carter0b744b32012-10-04 02:29:46 +00005954bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005955 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005956 StringRef IDVal = DirectiveID.getString();
5957
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005958 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005959 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005960 if (IDVal == ".cprestore")
5961 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005962 if (IDVal == ".dword") {
5963 parseDataDirective(8, DirectiveID.getLoc());
5964 return false;
5965 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005966 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005967 StringRef SymbolName;
5968
5969 if (Parser.parseIdentifier(SymbolName)) {
5970 reportParseError("expected identifier after .ent");
5971 return false;
5972 }
5973
5974 // There's an undocumented extension that allows an integer to
5975 // follow the name of the procedure which AFAICS is ignored by GAS.
5976 // Example: .ent foo,2
5977 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5978 if (getLexer().isNot(AsmToken::Comma)) {
5979 // Even though we accept this undocumented extension for compatibility
5980 // reasons, the additional integer argument does not actually change
5981 // the behaviour of the '.ent' directive, so we would like to discourage
5982 // its use. We do this by not referring to the extended version in
5983 // error messages which are not directly related to its use.
5984 reportParseError("unexpected token, expected end of statement");
5985 return false;
5986 }
5987 Parser.Lex(); // Eat the comma.
5988 const MCExpr *DummyNumber;
5989 int64_t DummyNumberVal;
5990 // If the user was explicitly trying to use the extended version,
5991 // we still give helpful extension-related error messages.
5992 if (Parser.parseExpression(DummyNumber)) {
5993 reportParseError("expected number after comma");
5994 return false;
5995 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005996 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005997 reportParseError("expected an absolute expression after comma");
5998 return false;
5999 }
6000 }
6001
6002 // If this is not the end of the statement, report an error.
6003 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6004 reportParseError("unexpected token, expected end of statement");
6005 return false;
6006 }
6007
Jim Grosbach6f482002015-05-18 18:43:14 +00006008 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006009
6010 getTargetStreamer().emitDirectiveEnt(*Sym);
6011 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006012 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006013 return false;
6014 }
6015
Jack Carter07c818d2013-01-25 01:31:34 +00006016 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006017 StringRef SymbolName;
6018
6019 if (Parser.parseIdentifier(SymbolName)) {
6020 reportParseError("expected identifier after .end");
6021 return false;
6022 }
6023
6024 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6025 reportParseError("unexpected token, expected end of statement");
6026 return false;
6027 }
6028
6029 if (CurrentFn == nullptr) {
6030 reportParseError(".end used without .ent");
6031 return false;
6032 }
6033
6034 if ((SymbolName != CurrentFn->getName())) {
6035 reportParseError(".end symbol does not match .ent symbol");
6036 return false;
6037 }
6038
6039 getTargetStreamer().emitDirectiveEnd(SymbolName);
6040 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006041 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006042 return false;
6043 }
6044
Jack Carter07c818d2013-01-25 01:31:34 +00006045 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006046 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6047 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006048 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006049 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6050 reportParseError("expected stack register");
6051 return false;
6052 }
6053
6054 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6055 if (!StackRegOpnd.isGPRAsmReg()) {
6056 reportParseError(StackRegOpnd.getStartLoc(),
6057 "expected general purpose register");
6058 return false;
6059 }
6060 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6061
6062 if (Parser.getTok().is(AsmToken::Comma))
6063 Parser.Lex();
6064 else {
6065 reportParseError("unexpected token, expected comma");
6066 return false;
6067 }
6068
6069 // Parse the frame size.
6070 const MCExpr *FrameSize;
6071 int64_t FrameSizeVal;
6072
6073 if (Parser.parseExpression(FrameSize)) {
6074 reportParseError("expected frame size value");
6075 return false;
6076 }
6077
Jim Grosbach13760bd2015-05-30 01:25:56 +00006078 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006079 reportParseError("frame size not an absolute expression");
6080 return false;
6081 }
6082
6083 if (Parser.getTok().is(AsmToken::Comma))
6084 Parser.Lex();
6085 else {
6086 reportParseError("unexpected token, expected comma");
6087 return false;
6088 }
6089
6090 // Parse the return register.
6091 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006092 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006093 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6094 reportParseError("expected return register");
6095 return false;
6096 }
6097
6098 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6099 if (!ReturnRegOpnd.isGPRAsmReg()) {
6100 reportParseError(ReturnRegOpnd.getStartLoc(),
6101 "expected general purpose register");
6102 return false;
6103 }
6104
6105 // If this is not the end of the statement, report an error.
6106 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6107 reportParseError("unexpected token, expected end of statement");
6108 return false;
6109 }
6110
6111 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6112 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006113 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006114 return false;
6115 }
6116
Jack Carter07c818d2013-01-25 01:31:34 +00006117 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00006118 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00006119 }
6120
Daniel Sandersd97a6342014-08-13 10:07:34 +00006121 if (IDVal == ".mask" || IDVal == ".fmask") {
6122 // .mask bitmask, frame_offset
6123 // bitmask: One bit for each register used.
6124 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6125 // first register is expected to be saved.
6126 // Examples:
6127 // .mask 0x80000000, -4
6128 // .fmask 0x80000000, -4
6129 //
Jack Carterbe332172012-09-07 00:48:02 +00006130
Daniel Sandersd97a6342014-08-13 10:07:34 +00006131 // Parse the bitmask
6132 const MCExpr *BitMask;
6133 int64_t BitMaskVal;
6134
6135 if (Parser.parseExpression(BitMask)) {
6136 reportParseError("expected bitmask value");
6137 return false;
6138 }
6139
Jim Grosbach13760bd2015-05-30 01:25:56 +00006140 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006141 reportParseError("bitmask not an absolute expression");
6142 return false;
6143 }
6144
6145 if (Parser.getTok().is(AsmToken::Comma))
6146 Parser.Lex();
6147 else {
6148 reportParseError("unexpected token, expected comma");
6149 return false;
6150 }
6151
6152 // Parse the frame_offset
6153 const MCExpr *FrameOffset;
6154 int64_t FrameOffsetVal;
6155
6156 if (Parser.parseExpression(FrameOffset)) {
6157 reportParseError("expected frame offset value");
6158 return false;
6159 }
6160
Jim Grosbach13760bd2015-05-30 01:25:56 +00006161 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006162 reportParseError("frame offset not an absolute expression");
6163 return false;
6164 }
6165
6166 // If this is not the end of the statement, report an error.
6167 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6168 reportParseError("unexpected token, expected end of statement");
6169 return false;
6170 }
6171
6172 if (IDVal == ".mask")
6173 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6174 else
6175 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006176 return false;
6177 }
6178
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006179 if (IDVal == ".nan")
6180 return parseDirectiveNaN();
6181
Jack Carter07c818d2013-01-25 01:31:34 +00006182 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006183 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006184 return false;
6185 }
6186
Rafael Espindolab59fb732014-03-28 18:50:26 +00006187 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006188 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006189 return false;
6190 }
6191
Jack Carter07c818d2013-01-25 01:31:34 +00006192 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006193 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006194 return false;
6195 }
6196
Jack Carter0cd3c192014-01-06 23:27:31 +00006197 if (IDVal == ".option")
6198 return parseDirectiveOption();
6199
6200 if (IDVal == ".abicalls") {
6201 getTargetStreamer().emitDirectiveAbiCalls();
6202 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006203 Error(Parser.getTok().getLoc(),
6204 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006205 // Clear line
6206 Parser.eatToEndOfStatement();
6207 }
6208 return false;
6209 }
6210
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006211 if (IDVal == ".cpsetup")
6212 return parseDirectiveCPSetup();
6213
Daniel Sandersf173dda2015-09-22 10:50:09 +00006214 if (IDVal == ".cpreturn")
6215 return parseDirectiveCPReturn();
6216
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006217 if (IDVal == ".module")
6218 return parseDirectiveModule();
6219
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006220 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
6221 return parseInternalDirectiveReallowModule();
6222
Toma Tabacu9ca50962015-04-16 09:53:47 +00006223 if (IDVal == ".insn")
6224 return parseInsnDirective();
6225
Rafael Espindola870c4e92012-01-11 03:56:41 +00006226 return true;
6227}
6228
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006229bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6230 // If this is not the end of the statement, report an error.
6231 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6232 reportParseError("unexpected token, expected end of statement");
6233 return false;
6234 }
6235
6236 getTargetStreamer().reallowModuleDirective();
6237
6238 getParser().Lex(); // Eat EndOfStatement token.
6239 return false;
6240}
6241
Rafael Espindola870c4e92012-01-11 03:56:41 +00006242extern "C" void LLVMInitializeMipsAsmParser() {
6243 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6244 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6245 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6246 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6247}
Jack Carterb4dbc172012-09-05 23:34:03 +00006248
6249#define GET_REGISTER_MATCHER
6250#define GET_MATCHER_IMPLEMENTATION
6251#include "MipsGenAsmMatcher.inc"